SQL按指定列分组统计不同值,实现product表各typePr下namePr计数需求
结论
该需求完全可以通过SQL实现,本质是行转列统计+可选JSON格式输出,根据使用的数据库不同写法会有细微差异,以下是通用实现思路和可直接运行的示例代码。
注:测试数据中id=2的
typePr值为typeeB疑似笔误,以下代码默认按正确值typeB统计,若保留原错误值,输出结果会额外多一条typeeB的分组。
场景1:namePr取值固定(已知只有nameA、nameB、nameC三个取值)
直接用条件聚合即可,写法适配所有支持SQL标准的数据库:
SELECT typePr, SUM(CASE WHEN namePr = 'nameA' THEN 1 ELSE 0 END) AS nameA, SUM(CASE WHEN namePr = 'nameB' THEN 1 ELSE 0 END) AS nameB, SUM(CASE WHEN namePr = 'nameC' THEN 1 ELSE 0 END) AS nameC FROM product GROUP BY typePr -- 过滤统计值全为0的分组,和预期结果对齐 HAVING nameA + nameB + nameC > 0;
如果需要直接输出要求的JSON数组格式,以MySQL 5.7+为例写法如下:
SELECT JSON_ARRAYAGG( JSON_OBJECT( 'typePr', typePr, 'nameA', NULLIF(nameA, 0), 'nameB', NULLIF(nameB, 0), 'nameC', NULLIF(nameC, 0) ) ) AS result FROM ( SELECT typePr, SUM(CASE WHEN namePr = 'nameA' THEN 1 ELSE 0 END) AS nameA, SUM(CASE WHEN namePr = 'nameB' THEN 1 ELSE 0 END) AS nameB, SUM(CASE WHEN namePr = 'nameC' THEN 1 ELSE 0 END) AS nameC FROM product GROUP BY typePr ) t;
若要完全匹配预期去掉JSON中值为null的键,可在应用层处理,或使用对应数据库的JSON过滤函数(如MySQL 8.0+可使用JSON_REMOVE配合路径表达式实现)。
场景2:namePr取值不固定,后续会新增其他取值
这种情况需要用动态SQL实现,以MySQL为例写法如下:
-- 拼接动态条件聚合语句 SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'SUM(CASE WHEN namePr = ''', namePr, ''' THEN 1 ELSE 0 END) AS ', namePr ) ) INTO @sql FROM product; -- 拼接完整查询语句 SET @sql = CONCAT('SELECT typePr, ', @sql, ' FROM product GROUP BY typePr'); -- 执行动态SQL PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
如果需要动态生成符合要求的JSON结构,在动态SQL中拼接JSON_OBJECT的参数即可。
内容的提问来源于stack exchange,提问作者4212
相关产品推荐
相关产品推荐

