first_value и last_value для каждого идентификатора пользователя - PullRequest
0 голосов
/ 26 октября 2018

Я пытаюсь получить первое запланированное время начала и последнее запланированное время окончания для каждого пользователя в моей таблице schedule_jobs для даты.

Я могу заставить его работать на одного пользователя, но при попытке для всех пользователей в день я могу получить последний раз, но не могу получить правильный первый раз, когда отображается время первого идентификатора пользователя для всех идентификаторов пользователя.

Вот мой код:

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 

Last_value отображается правильно для каждого user_id, однако first_value всегда показывает значение для первого user_id для всех.

Я попытался разбить их на разные запросы SELECT с помощью JOIN и запроса USING, но все еще получаю неправильные результаты для first_value.

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Почему бы просто не использовать 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, вы можете просто добавить целое число

0 голосов
/ 26 октября 2018

Вам необходимо предложение 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.Иногда это не будет работать, как ожидалось. Смотрите здесь

Вы должны использовать first_value с порядком DESC вместо:

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