如何从sal表动态获取r.sal值,实现多列统计需求?
from read_log r
inner join mes m on m.id = r.m_id
where
YEAR(m.send_date) = YEAR(curdate())
group by r.m_id
这段查询里,只有`r.sal`的取值会变化,最终每个`r.sal`值对应生成一列统计结果。现在`r.sal`已有80余种取值还在持续增加。 我想知道:能不能从存储了`1val`、`2val`、`3val`等值的`sal`表中获取匹配值?比如通过循环之类的方式实现类似`count(distinct case when r.sal = (select val from sal) then r.login end)`的逻辑(我知道这个写法不对,只是示例)。另外,`count(distinct case...`这种按`r.sal`分列统计的方式,有没有更优的实现方案? # 解决方案 ### 1. 动态生成SQL(适配sal值持续增加的场景) 因为`sal`表的取值一直在变,静态写一堆`case when`肯定不现实,得用动态SQL自动生成所有`sal`值对应的统计列。以MySQL为例,你可以用下面的方式实现: ```sql SET @sql = NULL; -- 从sal表拼接所有val对应的统计列语句 SELECT GROUP_CONCAT( DISTINCT CONCAT( 'count(distinct case when r.sal = ''', val, ''' then r.login end) as `', val, '`' ) ) INTO @sql FROM sal; -- 拼接完整SQL SET @sql = CONCAT( 'select r.m_id, ', @sql, ' from read_log r inner join mes m on m.id = r.m_id where YEAR(m.send_date) = YEAR(curdate()) group by r.m_id' ); -- 执行动态SQL PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
这段代码会自动读取sal表的所有val值,生成对应统计列,不用手动维护80多个case when。如果sal表的val值特别多,记得调整group_concat_max_len参数,避免SQL字符串被截断。
2. 行转列替代方案(避免大量列的困扰)
如果业务允许不用把每个sal值拆成单独列,而是以行形式展示结果,这种写法更简洁灵活,还不用管sal值新增:
select r.m_id, s.val as sal_value, count(distinct r.login) as login_count from read_log r inner join mes m on m.id = r.m_id inner join sal s on r.sal = s.val where YEAR(m.send_date) = YEAR(curdate()) group by r.m_id, s.val;
输出结果是三列:m_id、sal_value、login_count,每个m_id+sal组合对应一行数据。如果需要转成列格式,在应用层处理就行(比如用Python pandas透视表、Excel数据透视),比在SQL里硬转更省心。
3. 性能优化提示
不管用哪种方案,建议给这些字段加索引:
read_log(m_id, sal, login):覆盖查询所需字段,减少回表操作mes(id, send_date):加速表关联和日期过滤sal(val):如果sal表数据量大,提升关联匹配速度
内容的提问来源于stack exchange,提问作者fosfik
相关产品推荐
相关产品推荐

