我正在编写一个查询停车票数据库的查询,并计算每季度发布的停车票数量。
这里有两个活动部件。子查询使用generate_series生成15分钟的增量时间戳,并将其存储为“timestep”。然后外部查询使用另一个时间戳语句连接,该语句将所有内容舍入到最低的四分之一小时。
现在,它没有将null结果返回为“0”,这正是我试图通过连接完成的。
基本上,我正在寻找这样的输出:
12:00: 0 12:15: 10 12:45: 5 13:00: 0
......等等。
SELECT count(*), timer.timestep
FROM violations
left join (SELECT (hourstep || ':' || minutestep)::time AS timestep
from generate_series(0,23) AS hourstep,
generate_series(0,59, 15) AS minutestep)
AS timer
ON timer.timestep =
(extract(hour from violations."InfractionTime")
|| ':' ||
((extract(minute FROM violations."InfractionTime")::int / 15)*15))::time
GROUP BY timer.timestep
答案 0 :(得分:2)
我认为问题在于您将VIOLATIONS表作为左侧表,因此它是加入您的时间步结果集的基础。如果没有违规记录,则不关心您的时间步骤结果是否有条目。
我反转,所以你的LEFT-SIDE表是时间步的表,所以你总是得到所有15分钟的间隔...然后LEFT JOIN到违规。如果违规中没有记录,则应该保留时间段,但是如您所查找的那样为零。
SELECT
timer.timestep,
count(*)
FROM
( SELECT
(hourstep || ':' || minutestep)::time AS timestep
from
generate_series(0,23) AS hourstep,
generate_series(0,59, 15) AS minutestep) AS timer
LEFT JOIN violations
ON timer.timestep =
(extract(hour from violations."InfractionTime")
|| ':' ||
((extract(minute FROM violations."InfractionTime")::int / 15)*15))::time
group by
timer.timestep
答案 1 :(得分:0)
您LEFT JOIN
的切换台已经被清除。另外我建议更简单,更快查询:
SELECT step::time AS timestep, count(*) AS ct
FROM generate_series('2000-1-1 00:00'::timestamp
, '2000-1-1 23:45'::timestamp
, '15 min'::interval ) AS t(step)
LEFT JOIN violations v
ON v."InfractionTime"::time >= t.step::time
AND v."InfractionTime"::time < t.step::time + interval '15 min'
GROUP BY 1
ORDER BY 1
这使用了generate_series()
的第二种形式,可以直接使用时间戳。但不是time
,所以我参加了一个分期日并将结果投入时间(非常便宜!)
重写的查询使用sargable expressions进行连接,因此,如果查询表的较小样本,可以使用“InfractionTime”上的普通索引产生很好的效果。只要您查询整个表格,Postgres就会使用顺序扫描。