每个用户ID的first_value和last_value

时间:2018-10-26 13:14:26

标签: sql postgresql window-functions

我试图在我的schedule_jobs表中获取每个用户的第一个预定的开始时间和最后一个预定的结束时间。

我可以让它为一个用户使用,但是当每天为所有用户尝试时,我可以获取最后一次,但是第一次获取正确的时间却无法显示所有user_id的第一个user_id的时间。 / p>

这是我的代码:

SELECT DISTINCT on (user_id)
    user_id, first_value(scheduled_jobs.at) over (order by user_id, scheduled_jobs.at ASC),
    last_value(scheduled_jobs.to) over (order by user_id, scheduled_jobs.at DESC)
FROM scheduled_jobs
WHERE scheduled_jobs.at between CURRENT_DATE+INTERVAL'3 day' and CURRENT_DATE +INTERVAL '4 day'

当前结果示例:

user_id | first_value         | last_value
  19    | 2018-10-29 07:00:00 | 2018-10-29 17:00:00
  30    | 2018-10-29 07:00:00 | 2018-10-29 15:00:00
  37    | 2018-10-29 07:00:00 | 2018-10-29 16:30:00 

最后一个值正确显示每个user_id,但是first_value始终显示所有第一个user_id的值。

我尝试使用JOIN和USING查询将它们拆分为不同的SELECT查询,但是first_value的结果仍然不正确。

2 个答案:

答案 0 :(得分:2)

您需要一个PARTITION BY子句,该子句根据user_id生成帧

SELECT DISTINCT on (user_id)
    user_id, 
    first_value(sj.at) OVER (PARTITION BY user_id ORDER BY sj.at ASC),
    last_value(sj.to) OVER (PARTITION BY user_id ORDER BY sj.at DESC)
FROM 
    scheduled_jobs sj
WHERE 
    sj.at BETWEEN CURRENT_DATE + 3 and CURRENT_DATE + 4

其他:请使用last_value小心。有时它无法按预期工作。 See here

您应该将first_valueDESC一起使用:

first_value(scheduled_jobs.at) over (partition by user_id order by scheduled_jobs.at DESC)

答案 1 :(得分:1)

为什么不简单地使用min()max()?由于您没有选择任何其他列,因此distinct on()或窗口函数无需以以下内容开头:

SELECT user_id, 
       min(scheduled_jobs.at),
       max(scheduled_jobs.at)
FROM scheduled_jobs
WHERE scheduled_jobs.at between CURRENT_DATE + 3 and CURRENT_DATE + 4
group by user_id;

当您想为DATE值添加天数时,不需要使用interval,只需添加一个整数