我有一个基于 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 非零的行一起打印 - 例如,对于 ID 为 1 和 2 的两个坐标,zcount 为 0 的 1 月 25 日也应打印在例子-:
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;