基于Group By关联poll_opts与poll_voted两张投票数据表的技术问询
基于GROUP BY关联poll_opts与poll_voted表的实现方案
没问题,我来帮你实现这个基于GROUP BY关联两张投票表的操作。结合你的表结构,给你几个实用的SQL示例,还有关键细节的说明:
基础需求:统计每个投票选项的得票数
这是最常用的场景——统计指定投票(或所有投票)中每个选项的实际投票人数:
SELECT po.pid, po.oid, po.opt AS option_text, COUNT(pv.emp) AS vote_count FROM poll_opts po -- 使用LEFT JOIN确保没人投票的选项也能被保留(显示0票) LEFT JOIN poll_voted pv ON po.pid = pv.pid AND po.oid = pv.oid -- 可选:添加WHERE子句指定单个投票ID,去掉则统计所有投票的选项 WHERE po.pid = 1 GROUP BY po.pid, po.oid, po.opt ORDER BY po.pid, po.oid;
关键细节说明:
- LEFT JOIN的必要性:如果用
INNER JOIN,那些还没有任何投票的选项会被过滤掉;LEFT JOIN会保留poll_opts里的所有选项,没有投票的选项对应的vote_count会显示为0。 - COUNT(pv.emp)而非COUNT(*):
LEFT JOIN中未被投票的选项对应的pv字段都是NULL,COUNT(*)会把这些NULL行也统计成1,而COUNT(pv.emp)只会统计非NULL的投票记录,得到真实的得票数。 - GROUP BY的字段选择:因为
poll_opts的主键是(pid, oid),这两个字段已经能唯一标识一个选项;加上opt是为了在结果中显示选项文本,符合大多数SQL数据库的GROUP BY规则(非聚合字段必须出现在GROUP BY中)。
进阶需求:统计每个投票的选项得票占比
如果需要同时展示每个选项在所属投票中的得票百分比,可以结合窗口函数实现:
SELECT po.pid, po.oid, po.opt AS option_text, COUNT(pv.emp) AS vote_count, -- 计算当前选项在所属投票中的得票占比(保留2位小数) ROUND(COUNT(pv.emp) * 100.0 / SUM(COUNT(pv.emp)) OVER (PARTITION BY po.pid), 2) AS vote_percentage FROM poll_opts po LEFT JOIN poll_voted pv ON po.pid = pv.pid AND po.oid = pv.oid GROUP BY po.pid, po.oid, po.opt ORDER BY po.pid, vote_count DESC;
这里SUM(COUNT(pv.emp)) OVER (PARTITION BY po.pid)会计算每个投票的总票数,再用当前选项的得票数除以总票数得到百分比,ROUND()函数用来控制小数位数。
注意事项
- 一定要同时用
pid和oid作为JOIN条件:因为oid仅在单个投票内唯一,单独用oid关联会导致跨投票的错误匹配。 - 如果你的数据库开启了严格的GROUP BY模式(比如MySQL的
ONLY_FULL_GROUP_BY),务必保证SELECT中的非聚合字段都出现在GROUP BY列表中,否则会报错。
内容的提问来源于stack exchange,提问作者Sourav
相关产品推荐
相关产品推荐

