Postgres中的子查询根据sum函数给出不正确的结果

时间:2018-05-29 20:57:07

标签: postgresql common-table-expression postgresql-9.2

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 :(得分:0)

错误在最后一个语句中。您出于某种原因按每列进行分组,并在此处执行添加: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

实际上使用聚合函数为每个日期计算aseasi的计数,以便查询的最后部分如下所示

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

答案 1 :(得分:0)

WITH eas AS ( SELECT DATE_TRUNC('week',create_ts) AS DATE
,COUNT(name) AS ase FROM local WHERE type='sr' GROUP BY DATE_TRUNC('week',create_ts) ) , ias AS (
SELECT DATE_TRUNC('week',create_ts) AS DATE
,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

这解决了!!谢谢大家!