我有以下sql查询:
Create table that connects Candidate with Exam
** CandidateExam **
(FK) candidate_id: int
(FK) exam_id: int
查询工作非常好,但有很多重复。我在想怎么能让它干得更干?这是您可以用于实验的sql小提琴:
答案 0 :(得分:2)
使其更具可读性的一种方法是提取scores#>>'{medic,categories,food_insecurity}
:
SELECT
date(survey_results.created_at),
json_build_object(
'high', COUNT(*) FILTER (WHERE (sub.food in('high'))),
'medium', COUNT(*) FILTER (WHERE (sub.food in('medium'))),
'low', COUNT(*) FILTER (WHERE (sub.food in('low')))
) as food_insecurity,
json_build_object(
'high', COUNT(*) FILTER (WHERE (sub.motivation in('high'))),
'medium', COUNT(*) FILTER (WHERE (sub.motivation in('medium'))),
'low', COUNT(*) FILTER (WHERE (sub.motivation in('low')))
) as motivation
FROM survey_results
JOIN LATERAL (SELECT scores#>>'{medic,categories,motivation}',
scores#>>'{medic,categories,food_insecurity}'
) sub(motivation, food) ON true
GROUP BY date(survey_results.created_at);
<强> Rextester Demo 强>
另一个步骤可能是tablefunc
或某种旋转,以避免将high
“中\
低”声称为3次。
修改强>
使用json_object_agg
的版本:
WITH cte AS (
SELECT *
FROM survey_results
JOIN LATERAL (SELECT scores#>>'{medic,categories,motivation}',
scores#>>'{medic,categories,food_insecurity}'
) s1(motivation, food) ON true
)
SELECT cte.created_at::DATE
,MIN(s3.motivation)::json AS motivation
,MIN(s3.food_insecurity)::json AS food_insecurity
FROM cte
LEFT JOIN LATERAL (SELECT JSON_OBJECT_AGG(lvl, cnt_motivation)::text
,JSON_OBJECT_AGG(lvl, cnt_food)::text
FROM(SELECT sub2.lvl
,COUNT(*) FILTER (WHERE (sub2.lvl = sub.motivation))
,COUNT(*) FILTER (WHERE (sub2.lvl = sub.food))
FROM cte sub
CROSS JOIN (VALUES ('high'),
('medium'), ('low')) AS sub2(lvl)
GROUP BY sub2.lvl
) s2(lvl,cnt_motivation, cnt_food)
) s3(motivation,food_insecurity)
ON true
GROUP BY cte.created_at::DATE;
<强> Rextester Demo 2 强>