但是,当我检索它们时,我想在天边界处分割范围 – 例如:
2013-01-01 00:00:00 to 2013-01-02 23:59:59
将被选为两行:
2013-01-01 00:00:00 to 2013-01-01 23:59:59 2013-01-02 00:00:00 to 2013-01-02 23:59:59
对于两个检索到的条目,其他列中的值相同.
我已经看到this question似乎或多或少地解决了我想要的问题,但它是针对Postgresql的“非常老”的版本,所以我不确定它是否仍然适用.
我也看过this question,它完全符合我的要求,但据我所知,CONNECT BY语句是sql标准的Oracle扩展,所以我不能使用它.
我相信我可以使用Postgresql的generate_series来实现这一点,但是我希望有一个简单的例子可以证明它是如何用来做到这一点的.
这是我目前正在处理的查询,目前无效(因为我无法在连接的子查询中引用FROM表),但我相信这或多或少是正确的轨道.
Here’s the fiddle,包含架构,示例数据和我的工作查询.
更新:我刚刚发现一个有趣的事实,感谢this question,如果你在查询的SELECT部分使用set-returns函数,Postgresql将“自动”在集合和行上进行交叉连接.我想我已接近完成这项工作.
解决方法
包括下边框并在逻辑中的任何位置排除上边框.相比:
> Calculate number of concurrent events in SQL
在此前提的基础上:
Postgres 9.2或更高版本
SELECT id,stime,etime FROM timesheet_entries t WHERE etime <= stime::date + 1 -- this includes upper border 00:00 UNION ALL SELECT id,CASE WHEN stime::date = d THEN stime ELSE d END -- AS stime,CASE WHEN etime::date = d THEN etime ELSE d + 1 END -- AS etime FROM ( SELECT id,etime,generate_series(stime::date,etime::date,interval '1d')::date AS d FROM timesheet_entries t WHERE etime > stime::date + 1 ) sub ORDER BY id,stime;
或者干脆:
SELECT id,interval '1d')::date AS d FROM timesheet_entries t ) sub ORDER BY id,stime;
更简单的可能更快.
当stime和etime都完全落在00:00时,请注意角点差异.然后在末尾添加具有零时间范围的行.有各种方法可以解决这个问题.我提议:
SELECT * FROM ( SELECT id,CASE WHEN stime::date = d THEN stime ELSE d END AS stime,CASE WHEN etime::date = d THEN etime ELSE d + 1 END AS etime FROM ( SELECT id,interval '1d')::date AS d FROM timesheet_entries t ) sub1 ORDER BY id,stime ) sub2 WHERE etime <> stime;
Postgres 9.3
在Postgres 9.3中,你最好使用LAteraL
SELECT id,CASE WHEN etime::date = d THEN etime ELSE d + 1 END AS etime FROM timesheet_entries t,LAteraL (SELECT d::date FROM generate_series(t.stime::date,t.etime::date,interval '1d') d ) d ORDER BY id,stime;
Details in the manual.
与上述相同的角落情况.
SQL Fiddle展示全部.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。