从过去和未来获取最近的实例

时间:2015-09-18 20:48:47

标签: postgresql

我有一个包含appointment条记录的表格,用户会选择日期范围(begin_dateend_date)。我希望获得落在此日期范围内的appointment,以及过去和未来中最接近此日期范围的实例(也就是前一次出现和下一次出现)。

我认为解决这个问题的最佳方法是使用CTE和自联接,但我对另一种策略持开放态度。这是我目前的查询:

WITH present AS
(SELECT appt.ewssubject, appt.ewsstart::DATE, appt.ewsend::DATE 
FROM appointment appt
WHERE (appt.ewsstart, appt.ewsend) OVERLAPS (begin_date::DATE, end_date::DATE))

SELECT 
present.ewssubject, present.ewsstart, present.ewsend, 
past.ewssubject AS pastsubject, past.ewsstart::DATE AS paststart,past.ewsend::DATE AS pastend,
future.ewssubject AS futuresubject, future.ewsstart::date AS futurestart, future.ewsend::date AS futureend

FROM present 
LEFT JOIN appointment AS past USING (ewssubject)
LEFT JOIN appointment AS future USING (ewssubject)

WHERE 
present.ewssubject = past.ewssubject AND
present.ewssubject = future.ewssubject AND
past.ewsend < present.ewsstart AND
future.ewsstart > present.ewsend

ORDER BY present.ewsstart ASC

我得到了appointments的大量列表,并且有很多重复 - 就像这样:

subject  start       end         last_start  last_end    next_start  next_end
DINNER   2015-09-18  2015-09 18  2015-09-17  2015-09-17  2015-09-19  2015-09-19
DINNER   2015-09-18  2015-09 18  2015-09-17  2015-09-17  2015-09-19  2015-09-19
... // more repeats! :(

我想要做的就是减少重复次数,例如这种格式:

subject  start       end         last_start  last_end    next_start  next_end
DINNER   2015-09-18  2015-09-18  2015-09-17  2015-09-17  2015-09-19  2015-09-19
DINNER   2015-09-21  2015-09-21  2015-09-18  2015-09-18  2015-10-02  2015-10-02
... // and so on

n.b。 appointment可以跨越多天。

如何修复查询?或者还有另外一个我可以写的吗?

1 个答案:

答案 0 :(得分:1)

您没有输入有关数据的详细信息,因此我不确定这是否是个好主意,但您可以使用window functions

select
    ewssubject, ewsstart, ewsend,
    lag(ewsstart) over (partition by ewssubject order by ewstart) prior_start,
    lag(ewsend) over (partition by ewssubject order by ewstart) prior_end,
    lead(ewsstart) over (partition by ewssubject order by ewstart) next_start,
    lead(ewsend) over (partition by ewssubject order by ewstart) next_end
from appointment
order by ewstart;