将列名和数据获取到 SQL 中的行
Get column names and data to rows in SQL
我有一个 table,基本员工详细信息如下:
Table:tblEmployees
EmpID Name Contact Sex
100 John 55555 M
200 Kate 44444 F
300 Sam 88888 M
我想获得如下特定员工的查询结果,其中 EmpID = 200
Col1 Col2
EmpID 200
Name Kate
Sex F
您可以使用交叉应用:
select t.*
from employees e
cross apply (values
('empid', cast(empid as varchar(100))),
('name', name),
('sex', sex)
) t(attr, value)
where e.empid = 200
据推测,empid
是一个数字,因此需要显式转换(否则 sql 服务器将尝试将姓名和性别转换为数字,这将失败)。
attr | value
:---- | :----
empid | 200
name | Kate
sex | F
另一种选择是 XML
完全披露: 性能不如专线小巴的 CROSS APPLY
(+1) 或 UNPIVOT
。但它会动态地反透视几乎任何行、table、视图或临时查询,而无需实际使用动态 SQL.
例子
Declare @YourTable Table ([EmpID] varchar(50),[Name] varchar(50),[Contact] varchar(50),[Sex] varchar(50)) Insert Into @YourTable Values
(100,'John',55555,'M')
,(200,'Kate',44444,'F')
,(300,'Sam',88888,'M')
Select A.EmpID
,C.*
From @YourTable A
Cross Apply ( values (convert(xml,(select a.* for XML Raw ))) ) B(XMLData)
Cross Apply (
Select Item = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From XMLData.nodes('//@*') xNode(xAttr)
Where xAttr.value('local-name(.)', 'varchar(100)') not in ('EmpID','Other','Columns2Exclude')
) C
Returns
EmpID Item Value
100 Name John
100 Contact 55555
100 Sex M
200 Name Kate
200 Contact 44444
200 Sex F
300 Name Sam
300 Contact 88888
300 Sex M
编辑 - 如果对此处感兴趣,请使用 TVF 方法
Select A.EmpID
,B.*
From @YourTable A
Cross Apply [dbo].[tvf-XML-UnPivot-Row]((Select A.* for XML RAW)) B
TVF
CREATE FUNCTION [dbo].[tvf-XML-UnPivot-Row](@XML xml)
Returns Table
As
Return (
Select Item = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From @XML.nodes('//@*') xNode(xAttr)
)
或者涉及 3 个 UNION 的不太复杂的解决方案,假设字段名称是预先确定的。这可能在大表上表现更好。
如果您遇到性能问题,请分析执行计划并确保索引得到最佳利用。
由于您一次只寻找一名特定员工:
SELECT 'empid', convert(varchar(12), EmpID)
FROM tblEmployees
WHERE EmpID = 200
UNION ALL
SELECT 'name', name
FROM tblEmployees
WHERE EmpID = 200
UNION ALL
SELECT 'sex', sex
FROM tblEmployees
WHERE EmpID = 200
第一行 convert(varchar(12)
假设 EmpID 是一个 int
字段。
我有一个 table,基本员工详细信息如下:
Table:tblEmployees
EmpID Name Contact Sex
100 John 55555 M
200 Kate 44444 F
300 Sam 88888 M
我想获得如下特定员工的查询结果,其中 EmpID = 200
Col1 Col2
EmpID 200
Name Kate
Sex F
您可以使用交叉应用:
select t.*
from employees e
cross apply (values
('empid', cast(empid as varchar(100))),
('name', name),
('sex', sex)
) t(attr, value)
where e.empid = 200
据推测,empid
是一个数字,因此需要显式转换(否则 sql 服务器将尝试将姓名和性别转换为数字,这将失败)。
attr | value :---- | :---- empid | 200 name | Kate sex | F
另一种选择是 XML
完全披露: 性能不如专线小巴的 CROSS APPLY
(+1) 或 UNPIVOT
。但它会动态地反透视几乎任何行、table、视图或临时查询,而无需实际使用动态 SQL.
例子
Declare @YourTable Table ([EmpID] varchar(50),[Name] varchar(50),[Contact] varchar(50),[Sex] varchar(50)) Insert Into @YourTable Values
(100,'John',55555,'M')
,(200,'Kate',44444,'F')
,(300,'Sam',88888,'M')
Select A.EmpID
,C.*
From @YourTable A
Cross Apply ( values (convert(xml,(select a.* for XML Raw ))) ) B(XMLData)
Cross Apply (
Select Item = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From XMLData.nodes('//@*') xNode(xAttr)
Where xAttr.value('local-name(.)', 'varchar(100)') not in ('EmpID','Other','Columns2Exclude')
) C
Returns
EmpID Item Value
100 Name John
100 Contact 55555
100 Sex M
200 Name Kate
200 Contact 44444
200 Sex F
300 Name Sam
300 Contact 88888
300 Sex M
编辑 - 如果对此处感兴趣,请使用 TVF 方法
Select A.EmpID
,B.*
From @YourTable A
Cross Apply [dbo].[tvf-XML-UnPivot-Row]((Select A.* for XML RAW)) B
TVF
CREATE FUNCTION [dbo].[tvf-XML-UnPivot-Row](@XML xml)
Returns Table
As
Return (
Select Item = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From @XML.nodes('//@*') xNode(xAttr)
)
或者涉及 3 个 UNION 的不太复杂的解决方案,假设字段名称是预先确定的。这可能在大表上表现更好。 如果您遇到性能问题,请分析执行计划并确保索引得到最佳利用。
由于您一次只寻找一名特定员工:
SELECT 'empid', convert(varchar(12), EmpID)
FROM tblEmployees
WHERE EmpID = 200
UNION ALL
SELECT 'name', name
FROM tblEmployees
WHERE EmpID = 200
UNION ALL
SELECT 'sex', sex
FROM tblEmployees
WHERE EmpID = 200
第一行 convert(varchar(12)
假设 EmpID 是一个 int
字段。