Запрос для создания групп на основе активности

В моем сообществе мне нужно сегментировать пользователей по следующим критериям:

  • количество полученных лайков (30, 100, 200)
  • количество прочитанных постов (1 тыс., 2 тыс., 5 тыс.)
  • минимальное количество постов за последний год

Как я могу это сделать с помощью средства исследования данных?
Мне нужен запрос, в который я могу ввести эти параметры, и он выдаст список пользователей, чтобы я мог вручную добавить их в группу. Это должно быть очень просто.
Есть какие-то подсказки? С чего мне начать?

Я думаю, что что-то вроде этого может сработать:

-- [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

Это здорово!
Как узнать, был ли пост опубликован как минимум 10 раз за последний год?
Не просто одно упоминание, как в вашем запросе.

Как интегрировать этот запрос? Posts created for period

Просто уточним: вас интересуют лайки и прочитанные посты за всё время или эти показатели относятся также к последнему году?

Это подозрительно похоже на существующие группы уровней доверия (а их наполнение автоматизировано с помощью аналогичных мер) — почему бы вам просто не изменить существующие пороги и не получить всё готовое?

/admin/site_settings/category/trust

Например, для УД2 (участники находятся в trust_level_2 или эквиваленте в вашей терминологии):

Скрипт автоматизации теперь будет добавлять людей в группу, если они получат значок. Если вы можете использовать пользовательский SQL для значков, то это можно автоматизировать, но это похоже на уровни доверия.

Я вижу преимущества создания собственных уровней. Например, только TL3 опирается на минимальную вовлечённость в течение времени. Таким образом, можно также исключать пользователей из каждой собственной группы, если их вовлечённость снижается в течение года.

Кроме того, они не будут привязаны к стандартным возможностям и смогут использовать функции, доступные для групп, или конкретные премиум-категории.

Однако я не знаю, как именно настроена эта система, поэтому такая возможность может быть реализована через уровни доверия.

За всё время для лайков и прочитанных постов (первый критерий — чтобы сосредоточиться на качественных вкладах, а не просто на количестве постов; второй — для баланса).
Минимальное количество постов учитывается только за последний год — это параметр, позволяющий понять, остаются ли участники активными.

Это могло бы быть хорошим решением, но в моём случае мне пришлось бы значительно изменить уровни 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-файл (и открыть его, например, в Блокноте):

-- [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: Вам понадобится один значок (и один запрос для значка) для каждой группы, а также соответствующая автоматизация с использованием скрипта «Членство в группе пользователей через значок». Вы также можете автоматизировать выдачу значков, включив функцию «Пользовательские триггерные значки» (Enable Badge SQL и Creating triggered custom badge queries), вместо того чтобы выдавать их вручную.

Однако здесь задействовано множество компонентов, поэтому, возможно, на данном этапе лучше сохранить всё максимально простым.

Это потрясающе! Большое спасибо, Jammy

Не переживайте. :slight_smile: Надеюсь, с первым вы сможете проверить, получаете ли вы ожидаемые результаты, а второй должен упростить добавление их в группу. :+1:

Дайте знать, если что-то нужно будет подправить. :slight_smile:

Я объединил и улучшил их (с моими скромными навыками SQL). Если мне нужны имена пользователей, я просто скачиваю CSV и копирую/вставляю столбец с именами.
Я добавил likes_received_max, чтобы можно было разделять группы, исключая группу выше.

Например:
first_steps: 5 лайков (<30), 500 прочитанных постов, >5 постов за последний год,
beginners: 30 лайков (<100), 1000 прочитанных постов, >10 постов за последний год
padawan: 100 лайков, 2000 прочитанных постов, >10 постов за последний год
hero: 200 лайков, 5000 прочитанных постов, >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