跨列筛选Distinct记录:展会奖品获奖人数统计数据库问题
嘿,我来帮你解决这个统计难题!核心需求就是每个奖品只算一次同一个获奖者,不管他从多少个展位拿到,对吧?我分两种常见的数据库结构给你对应的解决方案:
情况1:所有获奖记录存在同一张标准表
如果你的数据库是规范设计的,比如有一张booth_awards表,每条记录对应一个展位的一次获奖,字段包括booth_id(展位ID)、participant_id(参与者唯一标识,比如手机号/会员ID)、prize_name(奖品名称)。那直接用GROUP BY加COUNT(DISTINCT)就能搞定:
SELECT prize_name, COUNT(DISTINCT participant_id) AS unique_winner_count FROM booth_awards GROUP BY prize_name;
这个语句会自动把同一个参与者多次拿同个奖品的情况合并,只统计一次,完美解决你的需求。
情况2:获奖记录按展位分了多列(非标准化结构)
如果你的表是按展位列来存获奖者的(比如列名是展位A获奖者、展位B获奖者,单元格里是逗号分隔的参与者ID),那得先把这些列转成行(也就是「unpivot」操作),再去重统计。不同数据库的写法略有不同:
MySQL/MariaDB 版本
SELECT prize_name, COUNT(DISTINCT participant_id) AS unique_winner_count FROM ( -- 拆分展位A的获奖者列 SELECT prize_name, TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(展位A获奖者, ',', n), ',', -1)) AS participant_id FROM your_table JOIN (SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) numbers ON CHAR_LENGTH(展位A获奖者) - CHAR_LENGTH(REPLACE(展位A获奖者, ',', '')) >= n - 1 UNION ALL -- 拆分展位B的获奖者列 SELECT prize_name, TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(展位B获奖者, ',', n), ',', -1)) AS participant_id FROM your_table JOIN (SELECT 1 n UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) numbers ON CHAR_LENGTH(展位B获奖者) - CHAR_LENGTH(REPLACE(展位B获奖者, ',', '')) >= n - 1 -- 有更多展位就继续加UNION ALL ) AS unpivoted_data GROUP BY prize_name;
这里的numbers子句是用来拆分逗号分隔的ID列表,你可以根据每个展位最多的获奖者数量调整数字个数(比如最多5个就加到SELECT 5)。
SQL Server 版本
SQL Server有现成的UNPIVOT和STRING_SPLIT函数,写起来更简洁:
SELECT prize_name, COUNT(DISTINCT value) AS unique_winner_count FROM ( SELECT prize_name, participant_id FROM your_table UNPIVOT ( participant_id FOR booth IN ([展位A获奖者], [展位B获奖者], [展位C获奖者]) ) AS unpvt ) AS unpivoted_data CROSS APPLY STRING_SPLIT(participant_id, ',') GROUP BY prize_name;
关键提醒
- 一定要用唯一的参与者标识(比如手机号、会员ID),别用姓名——重名会直接导致统计错误!
- 如果单元格里的ID带空格,记得用
TRIM()清理,不然同一个ID会被当成不同的记录。
如果你的表结构还有特殊情况(比如不同展位的奖品是分开的列),可以补充下具体的表结构,我再帮你调整语句!
内容的提问来源于stack exchange,提问作者Razgriz
相关产品推荐
相关产品推荐

