如何使用SQL PIVOT将值拆分到不同列且无重复、无NULL值
行转列合并查询实现方案
现有查询返回多行NULL的本质是三表关联后每个属性单独占一行,CASE WHEN仅给当前行匹配的属性列赋值,其余列默认返回NULL,没有按用户维度做行合并。两种可直接运行的实现方式如下:
方案1:聚合函数+GROUP BY(全SQL版本通用)
无需使用PIVOT语法,在你原有代码基础上调整即可,兼容性最好:
SELECT NameValue, MAX(CASE WHEN AttributeName = 'Phone Number' THEN AttributeValue END) AS PhoneNumber, MAX(CASE WHEN AttributeName = 'Age' THEN AttributeValue END) AS Age, MAX(CASE WHEN AttributeName = 'Gender' THEN AttributeValue END) AS Gender FROM #Name A INNER JOIN #AttValue B ON A.Name_id = B.Name_id INNER JOIN #Attribute C ON B.AttributeValue_id = C.AttributeValue_id GROUP BY NameValue
聚合函数使用
MAX/MIN均可,因为每个用户对应单个属性只会存在一个有效值,聚合时会自动忽略NULL值,将同一用户的不同属性合并到同一行。
方案2:PIVOT语法实现(适用于SQL Server、Oracle等支持PIVOT的数据库)
PIVOT语法专门用于行转列场景,编写逻辑为先取三表关联的明细数据,再指定转列的字段和聚合规则:
SELECT NameValue, [Phone Number] AS PhoneNumber, [Age] AS Age, [Gender] AS Gender FROM ( -- 子查询先输出三表关联后的基础明细:用户名、属性名、属性值 SELECT A.NameValue, C.AttributeName, B.AttributeValue FROM #Name A INNER JOIN #AttValue B ON A.Name_id = B.Name_id INNER JOIN #Attribute C ON B.AttributeValue_id = C.AttributeValue_id ) AS BaseData PIVOT( MAX(AttributeValue) FOR AttributeName IN ([Phone Number], [Age], [Gender]) ) AS PivotResult
两种写法执行后都会返回预期的单用户单行结果,示例数据下返回结果如下:
| NameValue | PhoneNumber | Age | Gender |
|---|---|---|---|
| Hannah | 01216892584 | 26 | Female |
内容的提问来源于stack exchange,提问作者Posey
相关产品推荐
相关产品推荐

