Подзапрос в Postgres дает неверный результат на основе функции суммы - PullRequest
0 голосов
/ 29 мая 2018
WITH eas AS
(
    SELECT 
    DATE_TRUNC('week',create_ts)::DATE - '1 day'::INTERVAL AS DATE           
    ,COUNT(name) AS ase
    FROM local
    WHERE  type='sr'
    GROUP BY DATE_TRUNC('week',create_ts)::DATE - '1 day'::INTERVAL
) 
, ias AS 
(       
    SELECT 
    DATE_TRUNC('week',create_ts)::DATE - '1 day'::INTERVAL AS DATE           
    ,COUNT(name) AS ase
    FROM local
    WHERE  type='sr'
    AND state NOT IN ('AZ','CA')
    GROUP BY DATE_TRUNC('week',create_ts)::DATE - '1 day'::INTERVAL
)
    SELECT 
    DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL AS l_create
    ,ase + asi AS count
    FROM eas FULL JOIN ias 
    ON ias.date = eas.date
    GROUP BY ase
    ,asi 
    ,DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL
    ORDER BY DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL ASC

Если я запускаю первый оператор, он дает следующий результат:

3/18/18 0:00    21
3/25/18 0:00    46
4/1/18 0:00     25
4/8/18 0:00     25

Второй оператор:

3/18/18 0:00    67
3/25/18 0:00    129
4/1/18 0:00     148
4/8/18 0:00     138

Если я выполняю полный запрос:

2018-03-18 00:00:00 175
2018-03-25 00:00:00 173
2018-04-01 00:00:00 163

В то время как желаемый результат:

3/18/18 0:00    88
3/25/18 0:00    175
4/1/18 0:00     173
4/8/18 0:00     163

Чего мне не хватает ??

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

WITH eas AS ( SELECT DATE_TRUNC('week',create_ts) AS DATE<br> ,COUNT(name) AS ase FROM local WHERE type='sr' GROUP BY DATE_TRUNC('week',create_ts) ) , ias AS (<br> SELECT DATE_TRUNC('week',create_ts) AS DATE<br> ,COUNT(name) AS ase FROM local WHERE type='sr' AND state NOT IN ('AZ','CA') GROUP BY DATE_TRUNC('week',create_ts) ) SELECT DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL AS l_create ,ase + asi AS count FROM eas FULL JOIN ias ON ias.date = eas.date GROUP BY ase ,asi ,DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL ORDER BY DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL ASC

Это исправлено !!Спасибо всем!

0 голосов
/ 30 мая 2018

Ошибка в последнем утверждении.По какой-то причине вы группируете по каждому столбцу и выполняете сложение здесь: ase + asi.Вместо этого я попытался бы заменить следующие строки:

,ase + asi AS count
...
GROUP BY ase, asi, DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL

на

,sum(ase)+sum(asi) AS count
...
GROUP BY DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL

, что фактически суммирует оба значения ase и asi для каждой даты с использованием функции агрегированиятак, чтобы последняя часть вашего запроса выглядела следующим образом:

SELECT 
DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL AS l_create
,sum(ase)+sum(asi) AS count
FROM eas FULL JOIN ias 
ON ias.date = eas.date
GROUP BY DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL
ORDER BY DATE_TRUNC('week',eas.date)::DATE - '1 day'::INTERVAL ASC

Для дальнейшего изучения причин, по которым это происходит, вам нужно отказаться от предложения GROUP BY и просмотреть данные, чтобы убедиться в том, чтоFULL JOIN делает.


Образец

Ниже я прилагаю образец истории, которая воспроизводит вашу проблему, но вместо столбца даты я использовал целое число (нетразница для вашего случая).

postgres=# create table a(dt int, cnt int);
CREATE TABLE
postgres=# create table b(dt int, cnt int);
CREATE TABLE
postgres=# insert into a values (1,21),(2,46),(3,25),(4,25);
INSERT 0 4
postgres=# insert into b values (1,67),(2,129),(3,148),(4,138);
INSERT 0 4
postgres=# select a.dt,sum(a.cnt)+sum(b.cnt) from a full join b on a.dt=b.dt group by a.dt order by a.dt;
 dt | ?column?
----+----------
  1 |       88
  2 |      175
  3 |      173
  4 |      163
...