在没有时区的时间戳的字段上加入没有时区的 generate_series 时间戳时遇到问题
Posted
技术标签:
【中文标题】在没有时区的时间戳的字段上加入没有时区的 generate_series 时间戳时遇到问题【英文标题】:Trouble joining generate_series timestamp without time zone on a field that's timestamp without timezone 【发布时间】:2019-10-10 19:13:11 【问题描述】:我正在尝试找出一种方法来报告有多少人同时在一个位置,精确到秒。 我有一张桌子,上面有这个人的 ID、他们输入的日期、他们输入的时间、他们离开的日期和他们离开的时间。 示例:
select unique_id, start_date, start_time, end_date, end_time
from My_Table
where start_date between '09/01/2019' and '09/02/2019'
limit 3
"unique_id" "start_date" "start_time" "end_date" "end_time"
989179 "2019-09-01" "06:03:13" "2019-09-01" "06:03:55"
995203 "2019-09-01" "11:29:27" "2019-09-01" "11:30:13"
917637 "2019-09-01" "11:06:46" "2019-09-01" "11:06:59"
我已将 start_date 和 start_time 以及 end_date 和 end_time 连接起来,因此它们是 2 个字段
select unique_id, ((start_date + start_time)::timestamp without time zone) as start_date,
((end_date + end_time)::timestamp without time zone) as end_date
结果示例:
"start_date"
"2019-09-01 09:28:54"
所以我将其设为 CTE,然后使用第二个 CTE,该 CTE 在日期到第二个之间使用 generate_series。
目标是,生成系列在两个日期之间的每一秒都会有一行。然后当我加入我的数据集时,我可以计算 my_table 中存在多少条记录,其中 start_date(plus time) 等于或大于 generate_series date_time 字段,end_date(plus time) 小于或等于 generate_series date_time字段。
我觉得这比它需要的更难解释。
理论上,如果有人从 2019-09-01 00:01:01 进入房间并在 2019-09-01 00:01:03 离开,我会将该记录计入 generate_series 行 2019-09 -01 00:01:01、2019-09-01 00:01:02 和 2019-09-01 00:01:03。
当我查看数据时,我可以看到我应该在特定的高峰期返回房间里的数百人。但查询返回全 0。
这可能是我需要调整的字段格式问题吗?
这里是查询:
with CTE as (
select unique_id, ((start_date+start_time)::timestamp without time zone) as start_date,
((end_date+end_time)::timestamp without time zone) as end_date
from My_table
where start_date between '09/01/2019' and '09/02/2019'
),
time_series as (
select generate_series( (date '2019-09-01')::timestamp, (date '2019-09-02')::timestamp, interval '1 second') as date_time
)
/*FINAL SELECT*/
select date_time, count(B.unique_id) as NumPpl
FROM (
select A.date_time
FROM time_series a
)x
left join CTE b on b.start_date >= x.date_time AND b.end_date <= x.date_time
GROUP BY 1
ORDER BY 1
(partial) result screenshot
提前谢谢你
我还应该添加我对该数据库的只读访问权限,因此我无法创建函数。
【问题讨论】:
【参考方案1】:简单版本:假设end_date
总是在start_date
之后,b.start_date >= x.date_time AND b.end_date <= x.date_time
永远不会为真。
加长版:generate_series()
也不需要 CTE,并且没有理由选择此 CTE 的所有列和所有行作为子查询。我还将删除原始数据的 CTE 并将其加入秒数(注意:这确实会以某种方式更改查询,因为您现在可能会考虑这些条目,其中 start_date
更早比2019-09-01
。如果你不想要这个,你可以再次将你的条件添加到连接条件中。但我想这是你真正想要的)。我还删除了一些不需要的演员表。试试这个:
SELECT gs.second, COUNT(my.unique_id)
FROM generate_series('2019-09-01'::timestamp, '2019-09-02'::timestamp, interval '1 second') gs (second)
LEFT JOIN my_table my ON (my.start_date + my.start_time) <= gs.second
AND (my.end_date + my.end_time) >= gs.second
GROUP BY 1
ORDER BY 1
【讨论】:
谢谢@Islingre 效果很好!非常感谢! 欢迎您@JasonSmith,并邀请您留下赞成票和接受;)以上是关于在没有时区的时间戳的字段上加入没有时区的 generate_series 时间戳时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章
javascript + postgres:时区和时间戳的使用
在带有/不带时区的日期或时间戳的查询中处理 generate_series()
将 Postgres 中没有时区的 DateTime 字段从中欧时间转换为 UTC