Как получить ВСЕ пользовательские теги сообщений (включая теги ответов) в Stack Exchange Data Explorer?
Я использую запрос в обозревателе данных стека Exchange (SEDE).
Это мой запрос:
SELECT A.Id
, A.PostTypeId
, A.Title
, A.Body
, A.ParentId
, A.Tags
, A.CreationDate
FROM posts A
LEFT JOIN users U
ON A.OwnerUserId = U.id
WHERE U.Id = ##UserId##
AND A.PostTypeId = 1
UNION
SELECT A.Id
, A.PostTypeId
, A.Title
, A.Body
, A.ParentId
, B.Tags
, A.CreationDate
FROM posts A
LEFT JOIN users U
ON A.OwnerUserId = U.id
RIGHT JOIN posts B
ON A.ParentId = B.Id
WHERE U.Id = ##UserId##
AND A.PostTypeId = 2
В приведенном выше коде сообщения в переполнении стека имеют 2 типа: вопрос и ответ. Вопросы(PostTypeId
1 в схеме базы данных) есть теги, но ответы (PostTypeId
2 в схеме базы данных) не имеют тегов. Ответы относятся к вопросам через ParentId
,
Но эффективность моего запроса выше слишком низкая, я могу получить только некоторые (используя идентификатор пользователя) теги сообщений.
Как я могу получить теги сообщений всех пользователей за время SEDE?
1 ответ
Несколько вещей:
- Вы не можете получить теги всех сообщений пользователя. В настоящее время насчитывается более 41 миллиона сообщений, и SEDE ограничивает результаты до 50000 строк.
- Итак, вам нужно: (A) каким-то образом ограничить результаты или (B) пролистать до 41 млн сообщений, по 50 Кб за раз (НЕ РЕКОМЕНДУЕТСЯ), или (C) использовать вместо этого Дамп данных или Google BigQuery($).
- Если вы не собираетесь ничего вытаскивать из
Users
таблица, но ID, то не включайте эту таблицу. Это жует циклы иPosts.OwnerUserId
это то же самое. - избежать
UNION
заявления по возможности (именно в этом случае). - При использовании
UNION
заявления, использоватьUNION ALL
если возможно (именно в этом случае). Это избавляет двигатель от необходимости делать повторные проверки.
Итак, вот план выполнения для исходного запроса:
Вот упрощенный план:
SELECT TOP 50000
p.OwnerUserId AS [User]
, p.Id AS [Post Id]
, CASE WHEN p.PostTypeId = 1 THEN 'Q' ELSE 'A' END AS [Type]
, COALESCE (p.Title, ownr.Title) AS [Title]
, p.Body
, COALESCE (p.Tags, ownr.Tags) AS [Tags]
, p.CreationDate
FROM Posts p
LEFT JOIN Posts ownr ON ownr.ID = p.ParentId
WHERE p.OwnerUserId = ##UserId##
AND p.PostTypeId IN (1, 2) -- Question, answer
ORDER BY p.OwnerUserId DESC, p.CreationDate
- что также дает более читаемые результаты - особенно когда WHERE
пункт удален.
Но, если вы можете ограничить, скажем, пользователем заранее; Вы получаете еще более эффективный запрос:
WITH usersOfInterest AS (
SELECT TOP 10
u.Id AS [UserId]
, u.DisplayName
FROM Users u
ORDER BY u.Reputation DESC
)
SELECT
[User] = 'site://u/' + CAST(u.UserId AS NVARCHAR) + '|' + CAST(u.UserId AS NVARCHAR)
, p.Id AS [Post Id]
, CASE WHEN p.PostTypeId = 1 THEN 'Q' ELSE 'A' END AS [Type]
, COALESCE (p.Title, ownr.Title) AS [Title]
, p.Body
, COALESCE (p.Tags, ownr.Tags) AS [Tags]
, p.CreationDate
FROM usersOfInterest u
INNER JOIN Posts p ON u.UserId = p.OwnerUserId
LEFT JOIN Posts ownr ON ownr.Id = p.ParentId
WHERE p.PostTypeId IN (1, 2) -- Question, answer
ORDER BY u.UserId DESC, p.CreationDate
(Этот запрос добавляет удобную гиперссылку на идентификатор пользователя.)
Обратите внимание, что только 10 лучших пользователей имеют более 50 тыс. Сообщений.