如何通过SQL关联多SELECT语句并实现行转列(空值留空)
解决行转列需求:将键值对表转为宽表
你的需求是把Persons表的键值对结构转成宽表(每个姓名一行,Info的不同取值作为列),缺失对应Info的单元格留空。下面提供两种可行方案,同时解释如何关联多个子查询:
方法1:条件聚合(推荐,通用所有SQL数据库)
这种方法仅需扫描一次表,代码简洁且性能更优,通过CASE语句配合聚合函数提取对应列的值,缺失值自动显示为NULL(空单元格)。
SELECT Name, MAX(CASE WHEN Info = 'Height' THEN Value END) AS Height, MAX(CASE WHEN Info = 'Weight' THEN Value END) AS Weight, MAX(CASE WHEN Info = 'Hair' THEN Value END) AS Hair FROM Persons GROUP BY Name ORDER BY Name;
说明
因为每个Name对应每个Info只有一条记录,用MAX(或MIN/SUM均可,这里MAX最直观)就能精准提取对应值;没有匹配Info时,CASE返回NULL,聚合后仍为NULL,即显示空单元格。
方法2:通过LEFT JOIN关联三个子查询
如果需要用子查询关联的方式实现,必须用LEFT JOIN而非INNER JOIN——INNER JOIN会过滤掉缺失任意Info的姓名,而LEFT JOIN能保留所有姓名,缺失值显示为NULL。
更清晰的写法是先获取所有唯一姓名作为基础表,再分别关联各Info的子查询:
SELECT n.Name, w.Weight, h.Height, hr.Hair FROM (SELECT DISTINCT Name FROM Persons) AS n LEFT JOIN (SELECT Name, Value AS Weight FROM Persons WHERE Info = 'Weight') AS w ON n.Name = w.Name LEFT JOIN (SELECT Name, Value AS Height FROM Persons WHERE Info = 'Height') AS h ON n.Name = h.Name LEFT JOIN (SELECT Name, Value AS Hair FROM Persons WHERE Info = 'Hair') AS hr ON n.Name = hr.Name ORDER BY n.Name;
说明
- 先通过
SELECT DISTINCT Name获取所有唯一姓名,确保不会遗漏任何行; - 对每个
Info对应的子查询做LEFT JOIN,即使某个姓名没有该Info的值,对应列也会显示空单元格; - 若直接关联三个子查询,需用
COALESCE处理姓名字段的NULL情况,但基础表+LEFT JOIN的写法更易维护。
内容的提问来源于stack exchange,提问作者Zqm
相关产品推荐
相关产品推荐

