После копания в коде у меня есть ответ:
Проблема в том, что наивный подход PostgreSQL до версии 12 приводит к неоправданно большим ошибкам округления в этом случае.
Давайте рассмотрим id = 'c742'
:
Формула для regr_slope
выглядит следующим образом:
regr_slope
: = ( N & sdot; & Sigma; ( X i & sdot; Y i ) - & Sigma; X i & sdot; & Sigma; Y i ) / ( N & sdot; & Sigma; ( X i 2 ) - & Sigma; X i & sdot; & Sigma; X i )
Проблема в делителе:
SELECT 2::float8 * (1552861322.149::float8 * 1552861322.149::float8 +
1552861322.455::float8 * 1552861322.455::float8) -
(1552861322.149::float8 + 1552861322.455::float8) *
(1552861322.149::float8 + 1552861322.455::float8);
?column?
----------
-2048
(1 row)
Поскольку результат отрицательный, PostgreSQL возвращает нулевой результат.
Этого бы не произошло при использовании точных вычислений (numeric
):
SELECT 2 * (1552861322.149 * 1552861322.149 +
1552861322.455 * 1552861322.455) -
(1552861322.149 + 1552861322.455) *
(1552861322.149 + 1552861322.455);
?column?
----------
0.093636
(1 row)
Поскольку PostgreSQL фиксирует e954a727f0c8872bf5203186ad0f5312f6183746 , все улучшается, и в PostgreSQL v12 PostgreSQL также возвращает правильный результат:
select id, regr_slope(elapsed, ts) from sb1 group by id;
id | regr_slope
------+-----------------------
c742 | 19.607858781290517
317e | -1.0838511987808963
5fe6 | 5.787509483586743e-06
3441 | -3.828395463097356
(4 rows)