每个用户 ID 的 first_value 和 last_value
Posted
技术标签:
【中文标题】每个用户 ID 的 first_value 和 last_value【英文标题】:first_value and last_value for each user id 【发布时间】:2018-10-26 13:14:26 【问题描述】:我正在尝试获取我的 scheduled_jobs 表中每个用户的第一个预定开始时间和最后一个预定结束时间。
我可以让它为一个用户工作,但是当我每天为所有用户尝试时,我可以获得最后一次,但是第一次显示所有 user_id 的第一个 user_id 的时间时无法获得正确的时间。
这是我的代码:
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 的 Last_value 显示正确,但 first_value 始终显示所有 user_id 的第一个值。
我尝试使用 JOIN 和 USING 查询将它们拆分为不同的 SELECT 查询,但对于 first_value 仍然得到不正确的结果。
【问题讨论】:
【参考方案1】:您需要一个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_value
和DESC
来代替:
first_value(scheduled_jobs.at) over (partition by user_id order by scheduled_jobs.at DESC)
【讨论】:
是的,这通过添加分区解决了我的问题,就像上面的答案一样【参考方案2】:为什么不简单地使用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
,只需添加一个整数即可
【讨论】:
是的,这解决了我的问题,也许我把它复杂化了。下面的答案也有效。不过,它只能让我将一个标记为已接受的答案。以上是关于每个用户 ID 的 first_value 和 last_value的主要内容,如果未能解决你的问题,请参考以下文章
Oracle分析函数-first_value()和last_value()
Oracle分析函数-first_value()和last_value()