SQL查询需求:将同一车辆的多属性条目合并为单条记录
合并车辆属性为单列表格记录的解决方案
嘿,这个需求完全可以通过数据库的聚合函数直接实现,不用在查询后再写代码处理~ 下面根据不同的主流数据库给你提供对应的SQL方案,完美匹配你想要的结果:
MySQL 实现
MySQL 提供了 GROUP_CONCAT 函数来聚合字符串,配合 CASE 可以实现你要的数组格式展示:
SELECT c.ID, c.Name, CASE WHEN COUNT(p.Property_name) > 1 THEN CONCAT('[', GROUP_CONCAT(p.Property_name SEPARATOR ', '), ']') ELSE COALESCE(GROUP_CONCAT(p.Property_name), 'None') END AS Property_name FROM Cars c LEFT JOIN `Car property` cp ON c.ID = cp.Car_ID LEFT JOIN Property p ON cp.property_ID = p.property_id GROUP BY c.ID, c.Name;
LEFT JOIN确保所有车辆(包括没有属性的Mercedes)都会被返回GROUP_CONCAT将同一车辆的所有属性名拼接成字符串CASE判断属性数量:多个属性时用方括号包裹,单个属性直接显示COALESCE处理无属性的情况,返回None
PostgreSQL 实现
PostgreSQL 使用 STRING_AGG 来完成字符串聚合,语法和逻辑类似:
SELECT c.ID, c.Name, CASE WHEN COUNT(p.Property_name) > 1 THEN CONCAT('[', STRING_AGG(p.Property_name, ', '), ']') ELSE COALESCE(STRING_AGG(p.Property_name, ', '), 'None') END AS Property_name FROM Cars c LEFT JOIN "Car property" cp ON c.ID = cp.Car_ID LEFT JOIN Property p ON cp.property_ID = p.property_id GROUP BY c.ID, c.Name;
注意PostgreSQL中带空格的表名需要用双引号" "包裹。
SQL Server 实现
SQL Server 2017+ 版本(支持STRING_AGG)
SELECT c.ID, c.Name, CASE WHEN COUNT(p.Property_name) > 1 THEN CONCAT('[', STRING_AGG(p.Property_name, ', '), ']') ELSE COALESCE(STRING_AGG(p.Property_name, ', '), 'None') END AS Property_name FROM Cars c LEFT JOIN [Car property] cp ON c.ID = cp.Car_ID LEFT JOIN Property p ON cp.property_ID = p.property_id GROUP BY c.ID, c.Name;
带空格的表名用方括号[]包裹。
SQL Server 2016及以下版本(无STRING_AGG)
需要用STUFF + FOR XML PATH的组合来模拟字符串聚合:
SELECT c.ID, c.Name, CASE WHEN COUNT(p.Property_name) > 1 THEN CONCAT('[', STUFF(( SELECT ', ' + p2.Property_name FROM [Car property] cp2 JOIN Property p2 ON cp2.property_ID = p2.property_id WHERE cp2.Car_ID = c.ID FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, ''), ']') ELSE COALESCE(( SELECT TOP 1 p2.Property_name FROM [Car property] cp2 JOIN Property p2 ON cp2.property_ID = p2.property_id WHERE cp2.Car_ID = c.ID ), 'None') END AS Property_name FROM Cars c LEFT JOIN [Car property] cp ON c.ID = cp.Car_ID LEFT JOIN Property p ON cp.property_ID = p.property_id GROUP BY c.ID, c.Name;
执行以上对应的SQL后,就能直接得到你期望的结果:同一车辆仅显示一条记录,属性合并到单个列中,无属性时显示None。
内容的提问来源于stack exchange,提问作者Barry
相关产品推荐
相关产品推荐

