sql - 如何使此 CTE 查询打印具有 0 值的行?

标签 sql postgresql join aggregate-functions common-table-expression

我有一个基于 CTE 的查询,我使用连接将大约 2600 个 4 元组纬度/经度值传递给它 - 这些纬度经度 4 元组已被 ID 标记并保存在称为坐标的第二个表中。这些左上角和右下角的纬度/经度值被传递到 CTE,以便显示在给定两个时间戳的这些坐标内发出的请求量(每小时)。-我能够在时间戳内获得每天的总请求数给定,即每个指定日期的用户请求总数。 (例如,用户选择查看每个星期三或星期三和星期四等 - 在 2012 年 1 月 1 日至 31 日之间的 11:55 和 22:04 之间,对于我通过的每个纬度/经度 4 元组。)但我无法获取这些行结果中 zcount 为 0,我只得到 zcount > 0 的行。我的查询如下:(给 Erwin Brandstetter 的注释,如果他看到这个,我检查了关于我之前问题的聊天室讨论并设置 coordinates 值到 NOT NULL 因为你说坐标可以是 null 通过设计,但我仍然有同样的问题不知何故。 - 虽然我可能我理解错了你的意思,因为当时我发烧得很厉害-

WITH v AS (
   SELECT '2012-1-1 11:55:11'::timestamp AS _from -- provide times once
         ,'2012-1-31 22:02:21'::timestamp AS _to
   )
, q AS (
   SELECT c.coordinates_id
        , date_trunc('hour', t.calltime) AS stamp
        , count(*) AS zcount
   FROM   v
   JOIN   mytable t ON  t.calltime BETWEEN v._from AND v._to
                   AND (t.calltime::time >= v._from::time AND
                        t.calltime::time <= v._to::time) AND 
(extract(DOW from t.calltime) = 3)
   JOIN   coordinates c ON (t.lat, t.lon) 
                   BETWEEN (c.bottomrightlat, c.topleftlon)
                       AND (c.topleftlat, c.bottomrightlon)
   GROUP BY c.coordinates_id, date_trunc('hour', t.calltime)
   )
, cal AS (
   SELECT generate_series('2012-1-1 11:00:00'::timestamp
                        , '2012-1-31 23:00:00'::timestamp
                        , '1 hour'::interval) AS stamp)
SELECT q.coordinates_id, cal.stamp::date, sum(q.zcount) AS zcount
FROM   v, cal
LEFT   JOIN q USING (stamp)
WHERE  extract(hour from cal.stamp) BETWEEN extract(hour from v._from)
                                        AND extract(hour from v._to)
AND    extract(DOW from cal.stamp) = 3 
AND    cal.stamp >= v._from
AND    cal.stamp <= v._to
GROUP  BY 1,2
ORDER  BY 1,2;

我执行这个查询时得到的输出基本上是这样的(通常我有大约 10354 行返回,不包括 zcount 为 0 的行,只是为了相似而提供两个坐标):

coordinates_id  | stamp      | zcount
1               ;"2012-01-04";      2
1               ;"2012-01-11";      3
1               ;"2012-01-18";      2
2               ;"2012-01-04";      2
2               ;"2012-01-11";      3
2               ;"2012-01-18";      2

但是,它应该是这样的,所有 zcount 为 0 的行也应该与 zcount 非零的行一起打印出来——例如January 25 with zcount 0 for the two coordinates with ID 1 and 2 也应该打印在example-的这一小部分:

coordinates_id  | stamp      | zcount
1               ;"2012-01-04";      2
1               ;"2012-01-11";      3
1               ;"2012-01-18";      2
1               ;"2012-01-25";      0
2               ;"2012-01-04";      2
2               ;"2012-01-11";      3
2               ;"2012-01-18";      2
2               ;"2012-01-25";      0

更新版本的 zcount 值比实际值大很多。 -还有 0 zcount 的行仍然没有显示-

WITH v AS (
   SELECT '2012-1-1 11:55:11'::timestamp AS _from -- provide times once
         ,'2012-1-31 22:02:21'::timestamp AS _to
   )
, q AS (
   SELECT c.coordinates_id
        , date_trunc('hour', t.calltime) AS stamp
        , count(*) AS zcount
   FROM   v
   JOIN   mytable t ON  t.calltime BETWEEN v._from AND v._to
                   AND (t.calltime::time >= v._from::time AND
                        t.calltime::time <= v._to::time) AND 
(extract(DOW from t.calltime) = 3)
   JOIN   coordinates c ON (t.lat, t.lon) 
                   BETWEEN (c.bottomrightlat, c.topleftlon)
                       AND (c.topleftlat, c.bottomrightlon)
   GROUP BY c.coordinates_id, date_trunc('hour', t.calltime)
   )
, cal AS (
   SELECT generate_series('2012-1-1 11:00:00'::timestamp
                        , '2012-1-31 23:00:00'::timestamp
                        , '1 hour'::interval) AS stamp)
, coordst AS ( 
   SELECT coordinates_id FROM coordinates)
SELECT q.coordinates_id, cal.stamp::date, COALESCE(sum(q.zcount),0) AS zcount
FROM   v, coordst, cal
LEFT   JOIN q USING (stamp)
WHERE  extract(hour from cal.stamp) BETWEEN extract(hour from v._from)
                                        AND extract(hour from v._to)
AND    extract(DOW from cal.stamp) = 3 
AND    cal.stamp >= v._from
AND    cal.stamp <= v._to
GROUP  BY 1,2
ORDER  BY 1,2;

最佳答案

您需要一个不同的 coordinates_id 列表来执行正确的 CROSS JOIN。 1. 在 WITH 中添加另一个条目。 2. 将其添加到您的 JOIN (FROM v,cal, coords)。 3. 您的 zcount 将显示 NULL,因此合并它。

WITH v AS (
   SELECT '2012-1-1 11:55:11'::timestamp AS _from -- provide times once
         ,'2012-1-31 22:02:21'::timestamp AS _to
   )
, q AS (
   SELECT c.coordinates_id
        , date_trunc('hour', t.calltime) AS stamp
        , count(*) AS zcount
   FROM   v
   JOIN   mytable t ON  t.calltime BETWEEN v._from AND v._to
                   AND (t.calltime::time >= v._from::time AND
                        t.calltime::time <= v._to::time) AND 
(extract(DOW from t.calltime) = 3)
   JOIN   coordinates c ON (t.lat, t.lon) 
                   BETWEEN (c.bottomrightlat, c.topleftlon)
                       AND (c.topleftlat, c.bottomrightlon)
   GROUP BY c.coordinates_id, date_trunc('hour', t.calltime)
   )
, cal AS (
   SELECT generate_series('2012-1-1 11:00:00'::timestamp
                        , '2012-1-31 23:00:00'::timestamp
                        , '1 hour'::interval) AS stamp)
, coordst AS ( 
   SELECT DISTINCT coordinates_id FROM coordinates)
SELECT coordst.coordinates_id, cal.stamp::date, COALESCE(sum(q.zcount),0) AS zcount
FROM   v CROSS JOIN coordst CROSS JOIN cal
LEFT   JOIN q USING q.stamp = cal.stamp AND coordst.coordinates_id = q.coordinates_id
WHERE  extract(hour from cal.stamp) BETWEEN extract(hour from v._from)
                                        AND extract(hour from v._to)
AND    extract(DOW from cal.stamp) = 3 
AND    cal.stamp >= v._from
AND    cal.stamp <= v._to
GROUP  BY 1,2
ORDER  BY 1,2;

关于sql - 如何使此 CTE 查询打印具有 0 值的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12760280/

相关文章:

mysql - 如何使用 SQL 查询从字母数字中获取数值并按数字排序

sql - 如何在 MySQL 中执行 FULL OUTER JOIN?

database - React Native - 连接到 PostgreSQL 数据库

mysql - 用于插入在 1 中大于最大值的值的 SQL 命令

Mysql获取加入/选择表的最新行(1 :n)

.net - 更新数据库记录中的单个字段时的最佳实践

仅当元素与 sql 相同时,Php 才回显用户信息

PostgreSQL 11 UNNEST 函数不存在

mysql - 如何使一条记录的值成为mysql上字段的标题?

mysql - 新手 : mysql join 2 tables to gether and count the results