لنفترض وجود 100 حل في شهر ما. هناك عشرون شخصًا ينتمون إلى مجموعة معينة، وبدأ الأشخاص في تصنيف ردودهم كحلول، ليصبح المجموع عشرون حلًا. أريد استعلامًا يمكنني من خلاله تحديد معرف المجموعة الأساسي الخاص بهم في السكربت، وجلب البيانات شهريًا لعرض النسبة لهذا الشهر على النحو التالي: 20/100 = 20%.
لقد حاولت جعل الاستعلامات أكثر تفصيلاً لتسهيل فهمها وصيانتها في المستقبل.
WITH users_groups AS (
SELECT
user_id,
g.id,
g.name group_name
FROM users u
INNER JOIN user_actions ua ON ua.user_id = u.id
LEFT JOIN groups g ON g.id = u.primary_group_id
WHERE ua.action_type = 15
GROUP BY user_id, g.id
),
tt_solution_by_month AS (
SELECT
date_part('year', created_at) AS year,
date_part('month', created_at) AS month,
COUNT(*) AS "total"
FROM user_actions ua
WHERE ua.action_type = 15
GROUP BY date_part('year', created_at), date_part('month', created_at)
ORDER BY date_part('year', created_at) ASC, date_part('month', created_at)
),
tt_solution_groups_by_month AS (
SELECT
date_part('year', created_at) AS year,
date_part('month', created_at) AS month,
ug.group_name,
COUNT(*) AS "tt_groups"
FROM user_actions ua
INNER JOIN users_groups ug ON ug.user_id = ua.user_id
WHERE ua.action_type = 15
GROUP BY ug.group_name, date_part('year', created_at), date_part('month', created_at)
ORDER BY date_part('year', created_at) ASC, date_part('month', created_at), ug.group_name)
SELECT
ts.year,
ts.month,
COALESCE(tsg.group_name,'without group'),
tt_groups,
total,
TRUNC((tt_groups::decimal/total::decimal) *100,1) AS "%"
FROM tt_solution_groups_by_month tsg
INNER JOIN tt_solution_by_month ts
ON ts.year = tsg.year AND ts.month = tsg.month
أخبريني إذا كان هذا هو النتيجة المتوقعة، أو إذا كان يجب عليّ تعديل أي شيء.
تقريبًا مثالي! لا أحتاج إلى عمود tt_groups أو العمود total، بل أحتاج فقط إلى رقم النسبة المئوية. أما بالنسبة لعمود group_name، فبما أن الاستعلام خاص بمجموعة واحدة، فلا داعي لإدراج هذا العمود أيضًا. سأحدد primary_group_id داخل كود الاستعلام، بحيث يبحث فقط عن حلول هذه المجموعة المحددة.
-- [params]
-- string :primary_group_id
WITH users_groups AS (
SELECT
user_id,
g.id,
g.name AS group_name
FROM users u
INNER JOIN user_actions ua ON ua.user_id = u.id
LEFT JOIN groups g ON g.id = u.primary_group_id
WHERE ua.action_type = 15
AND u.primary_group_id = :primary_group_id
GROUP BY user_id, g.id
),
tt_solution_by_month AS (
SELECT
date_part('year', created_at) AS year,
date_part('month', created_at) AS month,
COUNT(*) AS "total"
FROM user_actions ua
WHERE ua.action_type = 15
GROUP BY date_part('year', created_at), date_part('month', created_at)
ORDER BY date_part('year', created_at) ASC, date_part('month', created_at)
),
tt_solution_groups_by_month AS (
SELECT
date_part('year', created_at) AS year,
date_part('month', created_at) AS month,
ug.group_name,
COUNT(*) AS "tt_groups"
FROM user_actions ua
INNER JOIN users_groups ug ON ug.user_id = ua.user_id
WHERE ua.action_type = 15
GROUP BY ug.group_name, date_part('year', created_at), date_part('month', created_at)
ORDER BY date_part('year', created_at) ASC, date_part('month', created_at), ug.group_name)
SELECT
ts.year,
ts.month,
TRUNC((tt_groups::decimal/total::decimal) *100,1) AS "%"
FROM tt_solution_groups_by_month tsg
INNER JOIN tt_solution_by_month ts
ON ts.year = tsg.year AND ts.month = tsg.month