【问题标题】:first_value and last_value for each user id每个用户 ID 的 first_value 和 last_value
【发布时间】: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 仍然得到不正确的结果。

【问题讨论】:

    标签: sql postgresql window-functions


    【解决方案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_valueDESC 来代替:

    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,只需添加一个整数即可

    【讨论】:

    • 是的,这解决了我的问题,也许我把它复杂化了。下面的答案也有效。不过,它只能让我将一个标记为已接受的答案。
    猜你喜欢
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2020-10-18
    • 2013-03-01
    相关资源
    最近更新 更多