如何简化SQL查询 按日期统计总回答数与指定用户回答数
问题说明
现有两张数据库表:
questions表:包含date、question_id字段(原描述中写的questions_id为笔误,关联逻辑使用的是question_id)answers表:包含question_id、user_id字段
业务规则:单个用户可针对同一问题提交多条回答。
需求为按日期分组统计,输出包含date、all_answers_count、user_1_answers_count三个字段的结果,分别对应日期、当日总回答数、ID为1的用户当日回答数。
原有实现通过两次关联两表生成子查询再做关联,写法冗余且存在语法问题(缺GROUP BY、错误使用==做等值判断、多余的|符号),原SQL如下:
SELECT date, all_answers_count, user_1_answers_count FROM ( SELECT date, COUNT(user_id) as all_answers_count| FROM questions JOIN answers ON questions.question_id == answers.question_id ) as t1 JOIN ( SELECT date, COUNT(user_id) as user_1_answers_count FROM questions JOIN answers ON questions.question_id == answers.question_id WHERE user_id == 1 ) as t2 ON t1.date == t2.date
优化方案
不需要重复关联两次表,单次关联后使用条件聚合即可实现需求,写法更简洁、执行效率更高,兼容所有主流关系型数据库:
SELECT q.date, COUNT(a.user_id) AS all_answers_count, SUM(CASE WHEN a.user_id = 1 THEN 1 ELSE 0 END) AS user_1_answers_count FROM questions q INNER JOIN answers a ON q.question_id = a.question_id GROUP BY q.date;
适配特定数据库的简化写法
如果使用PostgreSQL、ClickHouse等支持FILTER子句的数据库,可以进一步简化条件计数的逻辑:
SELECT q.date, COUNT(a.user_id) AS all_answers_count, COUNT(a.user_id) FILTER (WHERE a.user_id = 1) AS user_1_answers_count FROM questions q INNER JOIN answers a ON q.question_id = a.question_id GROUP BY q.date;
补充说明:如果需要统计没有任何回答的日期,将
INNER JOIN替换为LEFT JOIN即可;如果仅需要统计有回答的日期,保留内连接写法性能更优。
内容的提问来源于stack exchange,提问作者user499353
相关产品推荐
相关产品推荐

