MySQL分组自动编号技术咨询:自定义查询与样本数据说明
解决MySQL查询中重复Items字段的优化方案
看起来你在使用MySQL用户变量生成排名时,遇到了拼接后的Items字段重复显示的问题——从你提供的样本数据来看,A. CARRIER: 1. UNDERCARRIAGE: 1.1 Track System Condition这类层级文本重复出现了多次。下面根据不同的需求场景,给出几种针对性的解决方案:
场景1:重复Items仅显示一次,后续重复行留空(MySQL 8.0+推荐)
如果希望相同的Items值只在第一次出现时显示,后续重复行的Items字段留空,可以使用LAG()窗口函数替代用户变量,代码更简洁且符合现代SQL标准:
SELECT ROW_NUMBER() OVER () AS rank, CASE WHEN LAG(CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup)) OVER (ORDER BY `Group`, SubGroup, TertiaryGroup) = CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup) THEN '' ELSE CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup) END AS Items, ItemGroup, item FROM myTable ORDER BY `Group`, SubGroup, TertiaryGroup;
说明:
LAG()函数会获取当前行的上一行Items值,与当前行对比;若相同则显示空字符串,否则显示拼接后的层级文本。ROW_NUMBER() OVER()替代原查询中的用户变量,自动生成连续排名。
场景2:仅保留每个唯一Items组的第一行(去重需求)
如果只需要每个唯一Items组的一条记录,可以通过子查询+DISTINCT或者窗口函数实现:
方法1:使用DISTINCT去重
SET @rank = 0; SELECT @rank:=@rank+1 AS rank, Items, ItemGroup, item FROM ( SELECT DISTINCT CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup) AS Items, ItemGroup, item FROM myTable ) AS unique_items;
方法2:窗口函数分组取第一行(更灵活)
SELECT ROW_NUMBER() OVER () AS rank, Items, ItemGroup, item FROM ( SELECT CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup) AS Items, ItemGroup, item, ROW_NUMBER() OVER (PARTITION BY `Group`, SubGroup, TertiaryGroup ORDER BY item) AS rn FROM myTable ) AS t WHERE rn = 1;
说明:
PARTITION BY按Group/SubGroup/TertiaryGroup分组,ORDER BY item指定每组内取第一行的排序规则。
场景3:统计每个唯一Items组的条目数(分组汇总)
如果想查看所有唯一的Items值,并统计每个组包含的条目数量,可以直接分组查询:
SET @rank = 0; SELECT @rank:=@rank+1 AS rank, CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup) AS Items, COUNT(*) AS item_count, -- 统计该组的条目总数 MAX(ItemGroup) AS ItemGroup, -- 根据实际需求选择聚合函数 MAX(item) AS item FROM myTable GROUP BY `Group`, SubGroup, TertiaryGroup ORDER BY `Group`, SubGroup, TertiaryGroup;
兼容MySQL 5.x版本的方案(无窗口函数)
如果你的MySQL版本低于8.0,不支持窗口函数,可以用用户变量模拟LAG()的效果:
SET @rank = 0; SET @prev_items = ''; SELECT @rank:=@rank+1 AS rank, CASE WHEN @prev_items = CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup) THEN '' ELSE @prev_items := CONCAT_WS(" ", `Group`, SubGroup, TertiaryGroup) END AS Items, ItemGroup, item FROM myTable ORDER BY `Group`, SubGroup, TertiaryGroup;
说明:
- 用
@prev_items保存上一行的Items值,每次对比后更新变量,实现重复值空显示的效果。
内容的提问来源于stack exchange,提问作者Vijunav Vastivch
相关产品推荐
相关产品推荐

