从同列提取不同值分列展示:ORDER_HISTORY表状态统计需求
行转列实现按门店统计各状态订单数
这是很常见的**行转列(Pivot)**需求,我给你几种实用的实现方案,适配不同的数据库场景:
一、静态状态值(已知所有状态类型)
如果你的状态值是固定的(比如只有53和57两种),用CASE WHEN是兼容性最好的方式,几乎所有数据库都支持:
SELECT store_id, -- 替换成你表中实际的门店字段名,比如shop_id COUNT(CASE WHEN Status = 53 THEN 1 END) AS order_cancelled, COUNT(CASE WHEN Status = 57 THEN 1 END) AS order_completed FROM ORDER_HISTORY GROUP BY store_id;
原理说明:
CASE WHEN会匹配对应状态值,符合条件返回1,否则返回NULLCOUNT()函数会自动忽略NULL值,因此刚好统计出对应状态的订单数量- 最后按门店分组,得到每个门店各状态的统计结果
如果你用的是支持PIVOT语法的数据库(比如SQL Server、Oracle),也可以用官方的行转列函数:
SQL Server 版本:
SELECT store_id, order_cancelled, order_completed FROM ( SELECT store_id, -- 替换为实际门店字段名 CASE Status WHEN 53 THEN 'order_cancelled' WHEN 57 THEN 'order_completed' END AS status_label FROM ORDER_HISTORY ) AS source PIVOT ( COUNT(status_label) FOR status_label IN ([order_cancelled], [order_completed]) ) AS pivot_result;
Oracle 版本:
SELECT store_id, -- 替换为实际门店字段名 order_cancelled, order_completed FROM ORDER_HISTORY PIVOT ( COUNT(*) FOR Status IN (53 AS order_cancelled, 57 AS order_completed) );
二、动态状态值(状态可能新增)
如果后续可能新增状态值,不想每次修改SQL,可以用动态SQL自动生成列。以MySQL为例:
-- 生成动态列的SQL片段 SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'COUNT(CASE WHEN Status = ', Status, ' THEN 1 END) AS ', CASE Status WHEN 53 THEN 'order_cancelled' WHEN 57 THEN 'order_completed' ELSE CONCAT('status_', Status) -- 未知状态用默认命名 END ) ) INTO @sql FROM ORDER_HISTORY; -- 拼接完整查询语句 SET @sql = CONCAT('SELECT store_id, ', @sql, ' FROM ORDER_HISTORY GROUP BY store_id'); -- 执行动态SQL PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
注意事项:
- 务必把所有SQL中的
store_id替换成你表中实际存储门店ID的字段名 - 动态SQL需要确保当前数据库账号有执行权限
- MySQL中如果状态值过多,可能需要调整
group_concat_max_len参数来避免截断
内容的提问来源于stack exchange,提问作者MeenuAbhi
相关产品推荐
相关产品推荐

