反透视数据时如何保留索引(SQL 服务器)
How to retain index when unpivoting data (SQL Server)
我正在尝试将 table 转换为 EAV 格式,但希望在每一行中保留一些额外的元数据。
初始Table
| Brand | Name | Number | Col1 | Col2 |
|-------|----------|--------|------|------|
| A | Book | #1 | 1 | 2 |
| B | Magazine | #2 | 1 | 2 |
期望输出
| Number | key | val |
|--------|-------|----------|
| #1 | Brand | A |
| #1 | Name | Book |
| #1 | Col1 | 1 |
| #1 | Col2 | 2 |
| #2 | Brand | B |
| #2 | Name | Magazine |
| #2 | Col1 | 1 |
| #2 | Col2 | 2 |
实际输出
Invalid column name 'Number'.
示例查询
select
[Number], -- How can this be selected?
[key],
[val]
from (
select
[Number],
[Brand],
[Name]
from [SomeTable]
) data
unpivot (
[val]
for [key] in (
[Brand],
[Name],
[Number],
[Col1],
[Col2]
)
) as unpiv
如何select一个键值对以及对应的数字作为索引?
您可以使用 CROSS APPLY
和一点 XML
如果 2016+,有一种 JSON 方法可以提高性能
例子
Declare @YourTable Table ([Brand] varchar(50),[Name] varchar(50),[Number] varchar(50),[Col1] int,[Col2] int)
Insert Into @YourTable Values
('A','Book','#1',1,2)
,('B','Magazine','#2',1,2)
Select A.Number
,C.*
From @YourTable A
Cross Apply ( values ( convert(xml,(select a.* for xml raw ) ) ) ) B(XMLData)
Cross Apply (
Select [key] = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From B.XMLData.nodes('//@*') xNode(xAttr)
Where xAttr.value('local-name(.)', 'varchar(100)') not in ('Number')
) C
Returns
Number key value
#1 Brand A
#1 Name Book
#1 Col1 1
#1 Col2 2
#2 Brand B
#2 Name Magazine
#2 Col1 1
#2 Col2 2
编辑 - 如果 2016+
添加了 JSON 版本
Select A.Number
,B.*
From @YourTable A
Cross Apply (
Select [Key]
,Value
From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper ))
Where [Key] not in ('Number')
) B
我正在尝试将 table 转换为 EAV 格式,但希望在每一行中保留一些额外的元数据。
初始Table
| Brand | Name | Number | Col1 | Col2 |
|-------|----------|--------|------|------|
| A | Book | #1 | 1 | 2 |
| B | Magazine | #2 | 1 | 2 |
期望输出
| Number | key | val |
|--------|-------|----------|
| #1 | Brand | A |
| #1 | Name | Book |
| #1 | Col1 | 1 |
| #1 | Col2 | 2 |
| #2 | Brand | B |
| #2 | Name | Magazine |
| #2 | Col1 | 1 |
| #2 | Col2 | 2 |
实际输出
Invalid column name 'Number'.
示例查询
select
[Number], -- How can this be selected?
[key],
[val]
from (
select
[Number],
[Brand],
[Name]
from [SomeTable]
) data
unpivot (
[val]
for [key] in (
[Brand],
[Name],
[Number],
[Col1],
[Col2]
)
) as unpiv
如何select一个键值对以及对应的数字作为索引?
您可以使用 CROSS APPLY
和一点 XML
如果 2016+,有一种 JSON 方法可以提高性能
例子
Declare @YourTable Table ([Brand] varchar(50),[Name] varchar(50),[Number] varchar(50),[Col1] int,[Col2] int)
Insert Into @YourTable Values
('A','Book','#1',1,2)
,('B','Magazine','#2',1,2)
Select A.Number
,C.*
From @YourTable A
Cross Apply ( values ( convert(xml,(select a.* for xml raw ) ) ) ) B(XMLData)
Cross Apply (
Select [key] = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
From B.XMLData.nodes('//@*') xNode(xAttr)
Where xAttr.value('local-name(.)', 'varchar(100)') not in ('Number')
) C
Returns
Number key value
#1 Brand A
#1 Name Book
#1 Col1 1
#1 Col2 2
#2 Brand B
#2 Name Magazine
#2 Col1 1
#2 Col2 2
编辑 - 如果 2016+
添加了 JSON 版本Select A.Number
,B.*
From @YourTable A
Cross Apply (
Select [Key]
,Value
From OpenJson((Select A.* For JSON Path,Without_Array_Wrapper ))
Where [Key] not in ('Number')
) B