MySQL如何将唯一列值转为列头?求通用客户统计动态列方案
MySQL动态行转列:按活动统计各事件的用户唯一计数与总计数
针对你的需求——统计每个campaign_name下,各event_name对应的customer_id唯一计数和总记录数,且event_name数量不固定,可通过MySQL动态SQL实现通用解决方案:
1. 先理解静态逻辑(固定事件场景)
如果已知所有event_name,可以用CASE表达式配合聚合函数实现:
SELECT campaign_name, -- event_1的唯一用户数 COUNT(DISTINCT CASE WHEN event_name = 'event_1' THEN customer_id END) AS event_1_unique_count, -- event_1的总记录数 COUNT(CASE WHEN event_name = 'event_1' THEN customer_id END) AS event_1_total_count, -- event_2的唯一用户数 COUNT(DISTINCT CASE WHEN event_name = 'event_2' THEN customer_id END) AS event_2_unique_count, -- event_2的总记录数 COUNT(CASE WHEN event_name = 'event_2' THEN customer_id END) AS event_2_total_count FROM event_data -- 替换成你的表名 GROUP BY campaign_name;
2. 动态SQL通用方案(适配任意数量的event_name)
由于event_name不固定,需要动态生成上述CASE语句,借助MySQL的预处理语句实现:
-- 临时调整GROUP_CONCAT的最大长度(如果事件数量多,按需设置) SET SESSION group_concat_max_len = 1000000; SET @sql = NULL; -- 动态生成每个事件对应的统计列片段 SELECT GROUP_CONCAT( DISTINCT CONCAT( 'COUNT(DISTINCT CASE WHEN event_name = ''', event_name, ''' THEN customer_id END) AS `', event_name, '_unique_count`, ', 'COUNT(CASE WHEN event_name = ''', event_name, ''' THEN customer_id END) AS `', event_name, '_total_count`' ) ) INTO @sql FROM event_data; -- 替换成你的表名 -- 拼接完整的查询语句 SET @sql = CONCAT( 'SELECT campaign_name, ', @sql, ' FROM event_data GROUP BY campaign_name' ); -- 执行动态生成的SQL PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
关键说明
- 用
GROUP_CONCAT遍历所有唯一的event_name,自动生成每个事件对应的两个统计列; - 列名用反引号``包裹,避免
event_name包含特殊字符导致SQL语法错误; - 如果你的表名不是
event_data,记得替换所有对应位置的表名。
内容的提问来源于stack exchange,提问作者abhijeet
相关产品推荐
相关产品推荐

