如何检测PostgreSQL中的重叠时间范围(How to detect overlapping time ranges in PostgreSQL)

编程入门 行业动态 更新时间:2024-10-14 06:17:55
如何检测PostgreSQL中的重叠时间范围(How to detect overlapping time ranges in PostgreSQL)

我有一张这样的桌子

CREATE TABLE public.userlocation ( datetime timestamp with time zone, location geometry, locationtype integer, buffer double precision, timebuffer double precision, "userID" numeric, "ID" integer NOT NULL DEFAULT nextval('"userlocation_ID_seq"'::regclass), "time" time with time zone )

每行有一个时间,然后是一个值来制作动态时间范围,实际上如果time=8且time=8 timebuffer=15那么时间范围将是endTime= 8+15min和startTime= 8-15 min 。我可以这样做只需使用这个查询

select f1.*,f1.time +(f1.timebuffer::text||' minute')::INTERVAL as startTime,f1.time-(f1.timebuffer::text||' minute')::INTERVAL as endTime

一切正常,在这个阶段之后,我想查询它们的时间段在startTime和endTime之间的行,而在其他单词中它们重叠。 我已经发现了这个问题

PostgreSQL查询检测重叠的时间范围

但是这里有区别,我没有开始时间和结束时间所以我必须使用上面的方法创建它们。 所以野兔是我的疑问

select f1.*,f1.time -(f1.timebuffer::text||' minute')::INTERVAL as startTime,f1.time+(f1.timebuffer::text||' minute')::INTERVAL as endTime from userlocation f1 where exists (select f2.time -(f2.timebuffer::text||' minute')::INTERVAL as startTime,f2.time+(f2.timebuffer::text||' minute')::INTERVAL as endTime from userlocation f2 where tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()') and f2.locationtype = f1.locationtype and f2.locationtype=1 and f2."ID" <> f1."ID");

但是我得到了这个错误

[2016-08-27 23:42:45] [42703] ERROR: column f2.starttime does not exist

职位:372

我想起初我应该创建F2表,但我不知道怎么样,你能给我一些提示吗?

I have a table like this

CREATE TABLE public.userlocation ( datetime timestamp with time zone, location geometry, locationtype integer, buffer double precision, timebuffer double precision, "userID" numeric, "ID" integer NOT NULL DEFAULT nextval('"userlocation_ID_seq"'::regclass), "time" time with time zone )

each row has a time and then a value to make a dynamic time range, in fact If time=8 and timebuffer=15so time range would be endTime= 8+15min and startTime= 8-15 min.I can do this simply using this query

select f1.*,f1.time +(f1.timebuffer::text||' minute')::INTERVAL as startTime,f1.time-(f1.timebuffer::text||' minute')::INTERVAL as endTime

everything work fine, After this stage I want to query rows that their time period is between startTime and endTime in other word they overlap. I have already found this question

PostgreSQL query to detect overlapping time ranges

But there is a difference here,I don't have start time and endtime so I have to create them using above method. so hare is my query

select f1.*,f1.time -(f1.timebuffer::text||' minute')::INTERVAL as startTime,f1.time+(f1.timebuffer::text||' minute')::INTERVAL as endTime from userlocation f1 where exists (select f2.time -(f2.timebuffer::text||' minute')::INTERVAL as startTime,f2.time+(f2.timebuffer::text||' minute')::INTERVAL as endTime from userlocation f2 where tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()') and f2.locationtype = f1.locationtype and f2.locationtype=1 and f2."ID" <> f1."ID");

But I get this error

[2016-08-27 23:42:45] [42703] ERROR: column f2.starttime does not exist

Position: 372

I think At first I should create F2 table but I dont know how,Can you please give me some hints?

最满意答案

第一:列别名( select expression AS somename ) 其查询中不可用,它只能从查询外部看到。 您可以通过将其包装到(subquery) xx或视图或CTE中来解决此问题

第二:不要重复自己:如果你需要计算两次相同的表达式,你可能做得太多了......


CREATE TEMP VIEW omg AS SELECT fx.*,fx.time -(fx.timebuffer::text||' minute')::INTERVAL as startTime ,fx.time+(fx.timebuffer::text||' minute')::INTERVAL as endTime , fx.locationtype , fx.ID -- ... maybe more columns and expressions ... FROM userlocation fx ; SELECT f1.startTime, f1.endTime -- ... maybe more columns and expressions ... FROM omg f1 WHERE EXISTS ( SELECT 1 FROM omg f2 WHERE tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()') AND f2.locationtype = f1.locationtype AND f2.locationtype=1 AND f2."ID" <> f1."ID") ; 而不是视图,你可以使用CTE(视图可能表现更好) 你也许可以将tsrange拉入视图或CTE 我没有检查逻辑

为了完整性,CTE版本(几乎看起来相同)

WITH omg AS ( SELECT fx.*,fx.time -(fx.timebuffer::text||' minute')::INTERVAL as startTime ,fx.time+(fx.timebuffer::text||' minute')::INTERVAL as endTime , fx.locationtype , fx.ID -- ... maybe more columns and expressions ... FROM userlocation fx ) SELECT f1.startTime, f1.endTime -- ... maybe more columns and expressions ... FROM omg f1 WHERE EXISTS ( SELECT 1 FROM omg f2 WHERE tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()') AND f2.locationtype = f1.locationtype AND f2.locationtype=1 AND f2."ID" <> f1."ID") ;

First: The column-alias (select expression AS somename) is not usable from within its query, it is only visible from outside the query. You can solve this by wrapping it into a (subquery) xx or a view or a CTE

Second: don't repeat yourself: if you need to compute the same expression(s) twice, you could be doing too much ...


CREATE TEMP VIEW omg AS SELECT fx.*,fx.time -(fx.timebuffer::text||' minute')::INTERVAL as startTime ,fx.time+(fx.timebuffer::text||' minute')::INTERVAL as endTime , fx.locationtype , fx.ID -- ... maybe more columns and expressions ... FROM userlocation fx ; SELECT f1.startTime, f1.endTime -- ... maybe more columns and expressions ... FROM omg f1 WHERE EXISTS ( SELECT 1 FROM omg f2 WHERE tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()') AND f2.locationtype = f1.locationtype AND f2.locationtype=1 AND f2."ID" <> f1."ID") ; instead of a view you could use a CTE (the view probably performs better) you could probably pull the tsrange into the view or CTE, too I didn't check the logic

For completeness, the CTE version (which almost looks the same)

WITH omg AS ( SELECT fx.*,fx.time -(fx.timebuffer::text||' minute')::INTERVAL as startTime ,fx.time+(fx.timebuffer::text||' minute')::INTERVAL as endTime , fx.locationtype , fx.ID -- ... maybe more columns and expressions ... FROM userlocation fx ) SELECT f1.startTime, f1.endTime -- ... maybe more columns and expressions ... FROM omg f1 WHERE EXISTS ( SELECT 1 FROM omg f2 WHERE tsrange(f2.startTime, f2.endTime, '()') && tsrange(f1.startTime, f1.endTime, '()') AND f2.locationtype = f1.locationtype AND f2.locationtype=1 AND f2."ID" <> f1."ID") ;

更多推荐

本文发布于:2023-08-05 19:40:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1437678.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:时间   detect   PostgreSQL   ranges   time

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!