PostgreSQL 및 DEV 파고들기
13448 단어 metatodayilearnedpostgressql
다음 쿼리는 사용자 ID와 오늘 이후로 사용자가 부정적인 중재자 반응이 없는 댓글을 두 개 이상 작성한 주를 찾습니다.
user_id
: 사용자의 데이터베이스 ID입니다. weeks_ago
: 댓글을 그룹화하는 주 수(오늘부터)number_of_comments_with_positive_reaction
: weeks_ago
에 대해 긍정적인 댓글이 몇 개 있었나요?SELECT user_id,
COUNT(user_id) as number_of_comments_with_positive_reaction,
/* Get the number of weeks, since today for posts */
(trunc((extract(epoch FROM (current_timestamp- created_at))) / 604800)) AS weeks_ago
FROM comments
/* Only select comments from the last 32 weeks that
don't have a negative moderator reaction */
INNER JOIN
/* Find all comments in the last 32 weeks */
(SELECT DISTINCT reactable_id
FROM reactions
WHERE reactable_type = 'Comment'
AND created_at > (now() - interval '224' day)
/* Omit any comments that got a negative moderator reaction */
EXCEPT
SELECT DISTINCT reactable_id
FROM reactions
WHERE reactable_type = 'Comment'
AND created_at > (now() - interval '224' day)
AND category IN ('thumbsdown', 'vomit')) AS positve_reactions
ON comments.id = positve_reactions.reactable_id
INNER JOIN
/* Find the users who have at least two comments in the last week */
(SELECT count(id) AS number_of_comments,
user_id AS comment_counts_user_id
FROM comments
WHERE created_at >= (now() - interval '7' day)
GROUP BY user_id) AS comment_counts
ON comments.user_id = comment_counts_user_id
AND comment_counts.number_of_comments > 1
/* Don’t select anything older than 224 days ago, or 32 weeks ago */
WHERE created_at > (now() - interval '224' day)
GROUP BY user_id, weeks_ago
위의 쿼리는 사용자 ID당 여러 행을 생성합니다. 괜찮습니다. 하지만 루프를 돌고 싶다면 일시적인 변수 마법을 터뜨려야 합니다.
이걸 하나의 쿼리로 줄일 수 있을지 궁금합니다. Forem의 몇몇 사람들의 도움을 받아 다음과 같은 쿼리를 작성하여 해당 정보를 집계했습니다. 하지만 약간의 조립 작업이 필요합니다.
열은 다음과 같습니다.
user_id
: 사용자의 데이터베이스 ID입니다. serialized_weeks_ago
: 의견이 있는 주의 쉼표로 구분된 목록입니다. weeks_ago_array
: serialized_weeks_ago
의 문자열이 아닌 표현인 정수 배열입니다. 우리는 ActiveRecord가 이 정수 배열을 어떻게 처리하는지 알고 싶습니다. serialized_weeks_ago
의 간단한 버전입니다. serialized_comment_counts
: 쉼표로 구분된 댓글 수 목록입니다. serialized_weeks_ago
의 첫 번째 숫자는 serialized_comment_counts
의 첫 번째 숫자에 매핑됩니다. 그리고 사용자당 하나의 행을 얻습니다.SELECT user_id,
/* A comma separated string of "weeks_ago" */
array_to_string(array_agg(weeks_ago), ',') AS serialized_weeks_ago,
/* Will active record convert this to an array of integers? */
array_agg(weeks_ago) AS weeks_ago_array,
/* A comma separated string of comment counts. The first value in this string
happens on the week that is the first value in serialized_weeks_ago */
array_to_string(array_agg(number_of_comments_with_positive_reaction), ',') AS serialized_comment_counts
FROM
/* This is the same query as the first example query */
(SELECT user_id,
COUNT(user_id) as number_of_comments_with_positive_reaction,
/* Get the number of weeks, since today for posts */
(trunc((extract(epoch FROM (current_timestamp- created_at))) / 604800)) AS weeks_ago
FROM comments
/* Only select comments from the last 32 weeks that
don't have a negative moderator reaction */
INNER JOIN
/* Find all comments in the last 32 weeks */
(SELECT DISTINCT reactable_id
FROM reactions
WHERE reactable_type = 'Comment'
AND created_at > (now() - interval '224' day)
/* Omit any comments that got a negative moderator reaction */
EXCEPT
SELECT DISTINCT reactable_id
FROM reactions
WHERE reactable_type = 'Comment'
AND created_at > (now() - interval '224' day)
AND category IN ('thumbsdown', 'vomit')) AS positve_reactions
ON comments.id = positve_reactions.reactable_id
INNER JOIN
/* Find the users who have at least two comments in the last week */
(SELECT count(id) AS number_of_comments,
user_id AS comment_counts_user_id
FROM comments
WHERE created_at >= (now() - interval '7' day)
GROUP BY user_id) AS comment_counts
ON comments.user_id = comment_counts_user_id
AND comment_counts.number_of_comments > 1
/* Don’t select anything older than 224 days ago, or 32 weeks ago */
WHERE created_at > (now() - interval '224' day)
GROUP BY user_id, weeks_ago
) AS user_comment_counts_by_week GROUP BY user_id
저는 이러한 PostgreSQL 접근 방식을 공유하고 싶습니다. 많은 작은 쿼리 실행을 우회하는 데 도움이 될 수 있기 때문입니다. 나는 또한 우리가 올바른 논리를 작성했고 그것이 충분히 성능이 있는지 확인하기 위해 두 사람과 짝을 이룰 기회가 있었습니다.
Reference
이 문제에 관하여(PostgreSQL 및 DEV 파고들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/devteam/digging-into-postgresql-and-dev-3e43텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)