활동 기반 그룹 생성 쿼리

저희 커뮤니티에서 다음 기준에 따라 사람들을 세분화해야 합니다:

  • 받은 좋아요 수 (30 - 100 - 200)
  • 읽은 게시물 수 (1천, 2천, 5천)
  • 지난 1년 동안의 최소 게시물 수

데이터 익스플로러를 사용하여 이 작업을 수행하는 방법은 무엇인가요?
해당 파라미터를 입력하면 사람들을 목록으로 보여주고, 이를 수동으로 그룹에 추가할 수 있는 쿼리를 작성하고 싶습니다. 매우 간단하게요.
어떤 힌트를 줄 수 있을까요? 어디서부터 시작해야 할까요?

이런 방식으로 하면 될 것 같습니다:

-- [params]
-- int :likes_received
-- int :posts_read

SELECT 
    us.user_id,
    us.likes_received,
    us.posts_read_count
FROM user_stats us
  JOIN users u on u.id = us.user_id
WHERE u.last_posted_at > CURRENT_DATE - INTERVAL '1 YEAR'
  AND us.likes_received >= :likes_received
  AND us.posts_read_count >= :posts_read
ORDER BY 2 DESC, 3 DESC

정말 좋습니다!
지난 1년 동안 게시물이 최소 10회 이상 조회되었는지 어떻게 확인할 수 있을까요?
질문에 있는 것처럼 조회가 1회인 경우만으로는 부족합니다.

이 쿼리를 어떻게 통합할 수 있을까요? Posts created for period

확인차 여쭤봅니다. 좋아요와 게시물 조회수는 전체 기간 기준으로 찾고 계신 건가요, 아니면 지난 1년 이내의 수치인가요?

기존의 신뢰 등급(Trust Level) 그룹과 매우 유사해 보입니다(그리고 해당 그룹의 인원은 유사한 기준으로 자동 설정됩니다) - 기존 임계값을 수정하면 자동으로 처리되지 않나요?

/admin/site_settings/category/trust

예를 들어 TL2의 경우(멤버는 trust_level_2 또는 사용 중인 방언에 해당하는 값):

자동화 스크립트는 이제 사용자가 배지를 획득하면 해당 그룹에 추가합니다. 배지에 대해 사용자 정의 SQL을 사용할 수 있다면 이를 자동화할 수 있지만, 신뢰 수준과 관련된 것 같습니다.

커스텀 그룹을 만들 때의 장점은 충분히 이해합니다. 예를 들어, TL3만 시간 경과에 따른 최소 참여도를 기준으로 합니다. 따라서 이런 방식으로 하면, 한 해 동안 참여도가 떨어지는 사용자는 각 커스텀 그룹에서 제외될 수 있을 것입니다.

또한, 기존 능력에 묶이지 않고, 그룹 활성화 기능이나 특정 프리미엄 카테고리를 활용할 수도 있습니다.

다만, 이 기능들의 구체적인 구성이 어떻게 되어 있는지 모르기 때문에, 신뢰 등급을 통해 구현할 수 있을지도 모릅니다.

좋아요와 게시물 읽음 수는 전체 기간 기준입니다(첫 번째는 단순 게시물이 아닌 좋은 기여도를 중시하기 위함이고, 두 번째는 이를 균형 있게 조정하기 위함입니다).
게시물 최소 수치는 지난 1년 내 기준으로만 적용되며, 이는 멤버들이 여전히 꾸준히 활동 중인지 파악하기 위한 파라미터입니다.

좋은 방법일 수 있지만, 제 경우에는 TL1, TL2, TL3을 크게 수정해야 하며 아래 제한 사항을 고려해야 합니다.

죄송하지만 이해가 되지 않습니다. 배지를 사용해야 하나요?
음, 위의 쿼리를 어떻게 수정해야 배지에 삽입할 수 있나요?

그 경우, 다음과 같은 쿼리를 사용하면 수동 조회를 제공할 수 있습니다:

-- [params]
-- int :likes_received
-- int :posts_read


WITH user_activity AS (

    SELECT 
        p.user_id, 
        COUNT(p.id) as posts_count
    FROM posts p
    LEFT JOIN topics t ON t.id = p.topic_id
    WHERE p.created_at::date >= CURRENT_DATE - INTERVAL '1 YEAR'
        AND t.deleted_at IS NULL
        AND p.deleted_at IS NULL
        AND t.archetype = 'regular'
    GROUP BY 1
)

SELECT 
    us.user_id,
    us.likes_received,
    us.posts_read_count,
    ua.posts_count
FROM user_stats us
  JOIN user_activity ua ON UA.user_id = us.user_id
WHERE us.likes_received >= :likes_received
  AND us.posts_read_count >= :posts_read
  AND ua.posts_count >= 10
ORDER BY 2 DESC, 3 DESC, 4 DESC

그리고 이를 조정하거나 사용자 이름만 남기도록 단순화하면, 결과를 CSV로 내보내고(예: 메모장 같은 프로그램으로 열면) 그룹 페이지의 ‘Add Users’ 상자에 복사하여 붙여넣을 수 있는 목록을 얻을 수 있습니다:

-- [params]
-- int :likes_received
-- int :posts_read


WITH user_activity AS (

    SELECT 
        p.user_id, 
        COUNT(p.id) as posts_count
    FROM posts p
    LEFT JOIN topics t ON t.id = p.topic_id
    WHERE p.created_at::date >= CURRENT_DATE - INTERVAL '1 YEAR'
        AND t.deleted_at IS NULL
        AND p.deleted_at IS NULL
        AND t.archetype = 'regular'
    GROUP BY 1
)

SELECT 
    u.username
FROM user_stats us
  JOIN user_activity ua ON UA.user_id = us.user_id
  JOIN users u ON u.id = us.user_id
WHERE us.likes_received >= :likes_received
  AND us.posts_read_count >= :posts_read
  AND ua.posts_count >= 10
ORDER BY 1

이것도 가능합니다. :partying_face: 각 그룹마다 배지(와 배지 쿼리) 하나씩이 필요하며, 'User Group Membership through Badge` 스크립트를 사용하는 자동화가 필요합니다. 수동으로 배지를 부여하는 대신 Custom Triggered Badges를 활성화하여 배지 부여도 자동화할 수 있습니다(Enable Badge SQL 및 Creating triggered custom badge queries).

다만, 움직이는 부품이 많으므로 이 단계에서는 단순하게 유지하는 것이 좋을 수 있습니다.

정말 놀랍네요! Jammy, 정말 감사합니다.

걱정 마세요. :slight_smile: 첫 번째로 예상하는 결과를 제대로 얻고 있는지 확인할 수 있을 거예요, 두 번째는 그룹에 추가하는 과정을 더 쉽게 만들어 줄 거예요. :+1:

조정이 필요한 부분이 있으면 말씀해 주세요. :slight_smile:

이들을 병합하고 개선했습니다 (제 부족한 SQL 실력으로요). 사용자명이 필요할 때는 CSV를 다운로드해서 사용자名列을 복사/붙여넣기 하면 됩니다.
likes_received_max를 추가해서 그룹을 나눌 수 있게 했습니다. 위의 그룹은 제외됩니다.

예를 들어
first_steps: 5개의 좋아요 (<30), 500개 게시글 읽음, 지난 1년간 5개 이상의 게시글 작성,
beginners: 30개의 좋아요 (<100), 1000개 게시글 읽음, 지난 1년간 10개 이상의 게시글 작성
padawan: 100개의 좋아요, 2000개 게시글 읽음, 지난 1년간 10개 이상의 게시글 작성
hero: 200개의 좋아요, 5000개 게시글 읽음, 지난 1년간 10개 이상의 게시글 작성

-- [params]
-- int :likes_received
-- int :posts_read
-- int :likes_received_max
-- int :posts_count



WITH user_activity AS (
    SELECT 
        p.user_id, 
        COUNT(p.id) as posts_count
    FROM posts p
    LEFT JOIN topics t ON t.id = p.topic_id
    WHERE p.created_at::date >= CURRENT_DATE - INTERVAL '1 YEAR'
        AND t.deleted_at IS NULL
        AND p.deleted_at IS NULL
        AND t.archetype = 'regular'
    GROUP BY 1
)

SELECT 
    us.user_id,
    u.username,
    us.likes_received,
    us.posts_read_count,
    ua.posts_count,
    u.title
FROM user_stats us
  JOIN user_activity ua ON UA.user_id = us.user_id
  JOIN users u ON u.id = us.user_id
WHERE us.likes_received >= :likes_received
  AND us.posts_read_count >= :posts_read
  AND ua.posts_count >= :posts_count
  AND us.likes_received < :likes_received_max
ORDER BY 2 ASC, 3 ASC, 4 ASC