В SQL как найти первую запись для пользователя, если она находится в пределах временного интервала, без сканирования всей БД - PullRequest
0 голосов
/ 08 декабря 2018

У меня есть база данных, user_requests, которая в основном выглядит так:

  user_id  |    request_timestamp    | request_type | other_metadata
-----------|-------------------------|--------------|----------------
  user1    |    2018-11-01:04:04:41  |    type1     | opaquedata_A
  user2    |    2018-11-01:04:03:41  |    type2     | opaquedata_B
  user1    |    2018-11-01:04:01:41  |    type1     | opaquedata_C
  user3    |    2018-11-01:04:05:41  |    type3     | opaquedata_D
  user4    |    2018-11-01:04:01:41  |    type4     | opaquedata_E

И она огромна .Выполнение какой-либо операции над всем этим абсолютно бесполезно, все должно быть похоже на то, «какие запросы были наиболее распространены в этом месяце », никто никогда не проверяет это в целом.

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

Однако я сталкиваюсь с проблемой, когда все мои обычные попытки ограничить это - найти «первый запрос в границах», а не «первый запрос , если он находится в пределах »

SELECT DISTINCT user_id,
              first_value(request_type) over (PARTITION BY user_id ORDER BY request_timestamp
                rows BETWEEN unbounded preceding and unbounded following) requestType,
              first_value(other_metadata) over (PARTITION BY user_id ORDER BY request_timestamp
                rows BETWEEN unbounded preceding and unbounded following) otherMetadata,
              first_value(request_timestamp) over (PARTITION BY user_id ORDER BY request_timestamp
                rows BETWEEN unbounded preceding and unbounded following) utteranceTimestamp
FROM user_requests
WHERE request_timestamp BETWEEN '2018-11-01' AND request_timestamp < '2018-12-01'

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

Есть идеи, как мне получить то, что я хочу, и при этом писать запросы, выполнение которых не занимает несколько часов?

1 Ответ

0 голосов
/ 08 декабря 2018

Требуется настраиваемая форма альтернативного запроса:

SELECT Curr.user_id, Curr.request_type, Curr.other_metadata, Curr.request_timestamp
FROM User_Requests Curr
WHERE  Curr.request_timestamp >='2018-11-01' 
       AND Curr.request_timestamp < '2018-12-01'
       AND NOT EXISTS (SELECT 1
                       FROM User_Requests Prev
                       WHERE Prev.user_id = Curr.user_id
                             AND Prev.request_timestamp < Curr.request_timestamp)

... Это находит все запросы за указанный период времени, а затемвыбрасывает любой, если есть ЛЮБОЙ более ранний запрос - в течение месяца или иным образом.Это не только получает самое раннее в месяце, но также имеет эффект игнорирования запросов в желаемом периоде, если есть и другие предыдущие запросы.

Для достижения наилучших результатов вам потребуется индекс на (user_id, request_timestamp).
(Обратите внимание, что я предполагаю, что оптимизатор работает хорошо и переводит ваши даты в надлежащие типы для ранжированного поиска. Возможно, вы захотите убедиться, что request_timestamp не приводится.)

Бонус LEFT JOIN - форма исключения, если она работает лучше.

SELECT Curr.user_id, Curr.request_type, Curr.other_metadata, Curr.request_timestamp
FROM User_Requests Curr
LEFT JOIN User_Requests Prev
       ON Prev.user_id = Curr.user_id
          AND Prev.request_timestamp < Curr.request_timestamp
WHERE  Curr.request_timestamp >='2018-11-01' 
       AND Curr.request_timestamp < '2018-12-01'
       AND Prev.user_id IS NULL
...