#sql #sql-server #tsql #group-by
#sql #sql-сервер #tsql #групповое-по
Вопрос:
Мне нужно выбрать всех пользователей, которые разместили более 3 сообщений в одной и той же категории (sql) за последний год с интервалом времени менее 15 дней. Проблема заключается в последней части «с интервалом времени менее 15 дней».
Вот как я выбираю пользователей на 2018 год и теги (вы можете запустить его на https://data.stackexchange.com/stackoverflow/query/new ):
SELECT OwnerUserId, Id, CreationDate
FROM Posts
WHERE OwnerUserId IN (
SELECT OwnerUserId
FROM Posts
WHERE YEAR(Posts.CreationDate) >= 2018 AND YEAR(Posts.CreationDate) < 2019
AND Posts.Tags LIKE '%sql%'
GROUP BY OwnerUserId,PostTypeId
HAVING COUNT(PostTypeId) > 3
)
Я думаю, что я должен сначала сгруппировать по диапазону дат, а затем посчитать. Но я не знаю, как это можно сделать. Я читал, как группировать по неделям, но это не то, что мне нужно, потому что сообщения могут быть за разные недели.
В конце концов, я должен просто получить список пользователей.
Комментарии:
1. Отличная идея использовать данные SEDE в качестве образца!
2. Как вы определяете «категорию»?
3. @GordonLinoff для примера я выбираю «sql». в этих данных это тег, потому что он есть почти в каждом сообщении
Ответ №1:
Вы можете использовать LAG
функцию с параметром смещения, чтобы найти дату 2-го предыдущего сообщения, а затем вычислить разницу в дате:
WITH questions AS (
SELECT OwnerUserId
, CreationDate AS PostDate
, LAG(CreationDate, 2) OVER (PARTITION BY OwnerUserId ORDER BY CreationDate) AS PrevDate
FROM Posts
WHERE OwnerUserId IS NOT NULL -- not community owned
AND PostTypeId = 1 -- questions only
AND CreationDate >= '2018-01-01' -- between 2018
AND CreationDate < '2019-01-01'
AND Tags LIKE '%<sql>%' -- tagged sql
)
SELECT *
FROM questions
WHERE DATEDIFF(DAY, PrevDate, PostDate) <= 14
Комментарии:
1. Большое спасибо, это именно то, что мне нужно!
Ответ №2:
Вы можете получать записи, соответствующие этим условиям, с помощью оконных функций. lead()
вы можете выбрать вторую запись после этой, а затем вы можете проверить, появляется ли она в течение правильного периода времени.
Если я правильно понимаю вашу терминологию:
select p.*
from (select p.*,
lead(CreationDate, 2) over (partition by OwnerUserId, PostTypeId order by CreationDate) as CreationDate_2
from posts p
where p.CreationDate >= '2018-01-01' and
p.CreationDate < '2019-01-01' and
p.Tags like '%sql%'
)
where CreationDate_2 < dateadd(day, 15, CreationDate)
Комментарии:
1. Извините, я новичок в sql, поэтому не могу быстро это исправить. я понимаю вашу идею, но она вернулась «Функция ‘lead’ должна иметь предложение OVER с ORDER BY».