检测重叠的日期/时间记录,并使用SQL显示它与哪些记录重叠

时间:2016-09-10 17:35:33

标签: sql postgresql

这里的挑战是使用SQL来使用日期/时间检测重叠的出价,并显示它与哪些出价重叠。

考虑表和记录:

-------------------------------------------------------------------
| person_id | bid_id  | start_at            | end_at              |
-------------------------------------------------------------------
| 1         | 10      | 2016-10-30 09:00 AM | 2016-10-30 11:00 AM |
| 1         | 20      | 2016-10-30 10:00 AM | 2016-10-30 12:00 PM |
| 1         | 30      | 2016-10-30 05:00 PM | 2016-10-30 06:00 PM |
| 1         | 40      | 2016-10-30 11:45 AM | 2016-10-30 02:00 PM |
| 2         | 50      | 2016-10-30 07:00 PM | 2016-10-30 08:00 PM |
| 2         | 60      | 2016-10-30 07:00 PM | 2016-10-30 08:00 PM |
| 2         | 70      | 2016-10-30 09:00 PM | 2016-10-30 10:00 PM |
-------------------------------------------------------------------

期望的输出:

--------------------------------------------
| person_id | bid_id | overlapping_bid_ids |
--------------------------------------------
| 1         | 10     | { 20 }              |
| 1         | 20     | { 10, 40 }          | 
| 1         | 40     | { 20 }              |
| 2         | 50     | { 60 }              |
| 2         | 60     | { 50 }              |
--------------------------------------------

1 个答案:

答案 0 :(得分:2)

您可以使用array_agg()和加入:

select b.person_id, b.bid_id, array_agg(b2.bid_id)
from bids b join
     bids b2
     on b2.person_id = b.person_id and
        b2.end_at > b.start_at and
        b2.start_at < b.end_at and 
        b2.bid_id <> b.bid_id 
group by b.person_id, b.bid_id;

请注意两个时间段重叠的逻辑。如果第一个在第二个结束之前开始而第一个结束在第一次结束之后开始,则它们重叠。这解释了部分重叠以及完全重叠。如果您愿意,也可以使用Postgres的ANSI标准范围运算符overlap的实现。