SQL 쿼리 작성에 대한 두 번째 연습
17149 단어 sqlpostgresmetaprogramming
Forem 인스턴스를 쿼리할 때 내 작업 표시
이것은 내 .
내가 작성할 쿼리는 활성 사용자 중 몇 퍼센트가 적어도 하나의 환영 기사에 댓글을 달았는지 답하는 데 도움이 됩니다. 이 쿼리에서 활성 사용자는 지난 7일 중 4일 동안 사이트에 있었던 사람입니다.
엔터티 관계 모델 설정
다시 말하지만 SQL을 작성할 때 관계 다이어그램으로 시작하는 것을 좋아합니다. 이 데이터 수집에는 4개의 관련 테이블이 있습니다.
class User
has_many :articles
has_many :comments
end
class Article
belongs_to :user
has_many :comments, as: :commentable
end
class Comment
belongs_to :commentable, polymorphic: true
belongs_to :user
end
class PageView
belongs_to :article
belongs_to :user, optional: true
end
아래는 네 가지 데이터 모델 중 엔터티 관계 모델(ERM)을 선호하는 사용자를 위한 다이어그램입니다.
이러한 쿼리에 사용된 테이블의 ERM입니다.
모든 활성 구성원 쿼리
지난 7일 중 최소 4일 동안
page_views
을(를) 보유한 모든 사용자를 원합니다. 이러한 "활성 사용자"를 고려할 것입니다.먼저 매우 좁은 쿼리를 작성하고 싶습니다. 내가 올바른 길을 가고 있다는 것을 확신하게 해주는 것. 페이지 조회수를 내
user_id
로 제한합니다.SELECT user_id, extract(isodow from created_at) AS day_of_week
FROM page_views
WHERE page_views.user_id = 702612
AND page_views.created_at > CURRENT_DATE - 7
GROUP BY page_views.user_id, day_of_week
다음 쿼리는 시간 초과되었습니다. 모든 사용자에게 쿼리하려고 합니다.
SELECT dow.user_id,
count(dow.day_of_week) AS number_of_days
FROM (
SELECT user_id,
extract(isodow from created_at) AS day_of_week
FROM page_views
WHERE page_views.created_at > CURRENT_DATE - 7
AND user_id IS NOT NULL
GROUP BY page_views.user_id, day_of_week
) AS dow
GROUP BY dow.user_id
HAVING count(dow.day_of_week) >= 4
페이지 조회수가 엄청나기 때문에 최근에 업데이트된 사용자로만 제한해야 합니다. 다음은 최근 사용자를 가져오는 쿼리입니다.
SELECT id
FROM users
WHERE updated_at
> CURRENT_DATE - 7
다음 쿼리는 "Forem의 현재 활성 사용자는 누구입니까?"라는 기본 질문입니다.
SELECT DISTINCT dow.user_id FROM (
SELECT users.id AS user_id,
extract(isodow from page_views.created_at) AS day_of_week
FROM users
INNER JOIN page_views
ON page_views.user_id = users.id
AND page_views.created_at > CURRENT_DATE - 7
AND user_id IS NOT NULL
-- Extend the window for users just a bit to account --
-- for timing variance --
WHERE users.updated_at
> NOW()::date - INTERVAL '8 day'
GROUP BY users.id, day_of_week) AS dow
GROUP BY dow.user_id
HAVING count(dow.day_of_week) >= 4
위의 쿼리를 에 "저장"했습니다. 이제 "현재 DEV.to의 활성 사용자"쿼리가 있습니다.
환영 게시물에 댓글을 단 활성 사용자 쿼리
다음 부분은 환영 게시물에 누가 모두 댓글을 달았는지 알아내는 것입니다. 에서 환영 기사에 댓글을 단 사용자 찾기에 대해 썼습니다.
그러나 코호트 쿼리를 조정해야 합니다. 환영 게시물에 댓글을 단 사용자 만 원합니다. 코호트 쿼리에는 환영 게시물에 댓글을 달거나 댓글을 달지 않은 사용자가 있습니다.
참고로 다음 쿼리의 결과는 환영 게시물에 댓글을 단 모든 사람
user_id
입니다. 그러나 사용자의 제한이 있음updated_at
SELECT DISTINCT comments.user_id AS user_id
FROM comments
INNER JOIN users
ON comments.user_id = users.id
-- Extend the window for users just a bit to --
-- account for timing variance --
AND users.updated_at > CURENT_DATE - 8
INNER JOIN articles
ON comments.commentable_id = articles.id
AND comments.commentable_type = 'Article'
AND articles.title LIKE 'Welcome Thread - v%'
AND articles.published = true
AND articles.user_id = 3
GROUP BY comments.user_id
이제 두 쿼리를 병합합니다. Postgresql
WITH
문을 사용하여 나중에 참조할 수 있는 두 개의 쿼리를 생성하고 있습니다. 쿼리를 "캡슐화"하는 데 도움이 되는 WITH
문을 찾았고 쿼리를 개념적으로 더 이해하기 쉽게 만들 수 있기를 바랍니다.WITH cow AS (
-- User IDs of recent folks who have commented on the
-- welcome threads --
SELECT DISTINCT comments.user_id AS user_id
FROM comments
INNER JOIN users ON comments.user_id = users.id
-- Extend the window for users just a bit to account --
-- for timing variance --
AND users.updated_at > CURENT_DATE - 8
INNER JOIN articles
ON comments.commentable_id = articles.id
AND comments.commentable_type = 'Article'
AND articles.title LIKE 'Welcome Thread - v%'
AND articles.published = true
AND articles.user_id = 3
GROUP BY comments.user_id
), dow AS (
-- User IDs of folks who have interacted at least 4 different
-- days of this week --
SELECT user_id FROM (
SELECT users.id AS user_id,
extract(isodow from page_views.created_at) AS day_of_week
FROM users
INNER JOIN page_views
ON page_views.user_id = users.id
AND page_views.created_at > CURRENT_DATE - 7
AND user_id IS NOT NULL
-- Extend the window for users just a bit to account for
-- timing variance --
WHERE users.updated_at > CURRENT_DATE - 8
GROUP BY users.id, day_of_week
) AS dows
GROUP BY user_id
HAVING COUNT(day_of_week) >= 4
)
SELECT COUNT(dow.user_id) AS count_of_users,
(
SELECT COUNT(*)
FROM dow
INNER JOIN cow
ON cow.user_id = dow.user_id
) AS count_of_users_that_said_hello
FROM dow
결론
마지막 쿼리를 작성할 때 사이트의 모든 활성 사용자가 환영 기사에 댓글을 달았다는 결과를 계속 얻었습니다. 나는 그 결과를 믿지 않았다. 가능성이 매우 희박해 보였습니다. 내 쿼리와 논리를 재검토하고 내 오류를 발견하고 쿼리를 재작업하여 보다 합리적인 답변을 얻었습니다.
무엇이 잘못되었나요? 에서 쿼리를 복사하여 붙여넣었습니다. 하지만 그 질문은 올바른 질문이 아니었습니다. SQL의 한 가지 문제를 강조합니다. 쿼리의 정확성을 테스트하기 어려울 수 있습니다.
Reference
이 문제에 관하여(SQL 쿼리 작성에 대한 두 번째 연습), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/devteam/a-second-walk-through-of-composing-a-sql-query-561b텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)