根据公共列值将定义的行数转换为列
Posted
技术标签:
【中文标题】根据公共列值将定义的行数转换为列【英文标题】:Pivoting a defined number of rows into columns according to a common column value 【发布时间】:2021-06-02 19:16:50 【问题描述】:我在 SQL Server 中的表中有以下数据集,如下所示:
Table Name: Metadata
IdMetadata IdMetadataKey Value IdBatch
1 3 50550000 105
2 2 ABC 105
3 5 Buks 105
4 1 Bruwer 105
5 4 AB1234567/4 105
6 6 Annuity Tax Directive 105
7 3 50594644 105
8 2 ABC 105
9 5 Jami 105
10 1 Leigh 105
11 4 9401213056080 105
12 6 Redemption 105
13 3 50550026 106
14 2 ABC 106
15 5 John 106
16 1 Smith 106
17 4 6812305023089 106
18 6 Tax Free Transfer Out 106
IdMetadataKey 中的列值是指向以下主表的外键
Table Name: MetadataKey
IdMetadataKey Description
1 LAST_NAME
2 COMPANY
3 INVESTOR_ID
4 IDENTIFICATION_NUMBER
5 FIRST_NAME
6 WORK_DESCRIPTION
我想使用上面提到的第一个表来完成以下内容:
Investor_Id First_Name Last_Name ID_Number Work_Description Company IdBatch
50550000 Buks Bruwer AB1234567/4 Annuity Tax Directive ABC 105
50594644 Jami Leigh 555254 Redemption ABC 105
50550026 John Smith 9958586 Tax Free Transfer Out ABC 106
对上述结果的解释是这样的:
以 IdBatch 105,找到所有投资者及其相关 该批次的信息。因此批次 105 有 2 条记录
IdBatch 106 也是如此。但这里只有一条记录(投资者) 找到了
我曾尝试在 SQL 中使用 Pivot
命令来实现该结果,但无法使其正常工作。任何人都可以提出一种获得所需结果的方法。
附注:表元数据中的批次总是有 6 (* n) 行。
【问题讨论】:
【参考方案1】:您可以在 sql server 中使用静态数据透视轻松完成。在我看来,将两个表连接起来以获取数据透视表的列标题而不是在查询中硬编码地提及它们将是一种更好的方法。
架构和插入语句:
create table metadata(IdMetadata int, IdMetadataKey int, Value varchar(50), IdBatch int);
insert into metadata values(1, 3 ,'50550000', 105);
insert into metadata values(2, 2 ,'ABC', 105);
insert into metadata values(3, 5 ,'Buks', 105);
insert into metadata values(4, 1 ,'Bruwer', 105);
insert into metadata values(5, 4 ,'AB1234567/4', 105);
insert into metadata values(6, 6 ,'Annuity Tax Directive', 105);
insert into metadata values(7, 3 ,'50594644', 105);
insert into metadata values(8, 2 ,'ABC', 105);
insert into metadata values(9, 5 ,'Jami', 105);
insert into metadata values(10, 1 ,'Leigh', 105);
insert into metadata values(11, 4 ,'9401213056080', 105);
insert into metadata values(12, 6 ,'Redemption', 105);
insert into metadata values(13, 3 ,'50550026', 106);
insert into metadata values(14, 2 ,'ABC', 106);
insert into metadata values(15, 5 ,'John', 106);
insert into metadata values(16, 1 ,'Smith', 106);
insert into metadata values(17, 4 ,'6812305023089', 106);
insert into metadata values(18, 6 ,'Tax Free Transfer Out', 106);
create table MetadataKey(IdMetadataKey int, Description varchar(50));
insert into MetadataKey values(1, 'LAST_NAME');
insert into MetadataKey values(2, 'COMPANY');
insert into MetadataKey values(3, 'INVESTOR_ID');
insert into MetadataKey values(4, 'IDENTIFICATION_NUMBER');
insert into MetadataKey values(5, 'FIRST_NAME');
insert into MetadataKey values(6, 'WORK_DESCRIPTION');
查询:
select max(Investor_Id)Investor_Id, max(First_Name)First_Name, max(Last_Name)Last_Name, max(IDENTIFICATION_NUMBER), max(Work_Description)Work_Description, max(Company)Company, max(IdBatch)IdBatch
from
(
select md.*, mdk.Description,row_number()over(partition by idbatch,md.idmetadatakey order by idmetadata)rnk from metadata md inner join metadatakey mdk on md.idMetadataKey=mdk.idMetadataKey
) As SourceTable
Pivot
(
max(value) for Description in (Investor_Id, First_Name, Last_Name, IDENTIFICATION_NUMBER, Work_Description, Company)
) as P
Group by IdBatch,rnk
order by idbatch,investor_id
输出:
Investor_Id | First_Name | Last_Name | (No column name) | Work_Description | Company | IdBatch |
---|---|---|---|---|---|---|
50550000 | Buks | Bruwer | AB1234567/4 | Annuity Tax Directive | ABC | 105 |
50594644 | Jami | Leigh | 9401213056080 | Redemption | ABC | 105 |
50550026 | John | Smith | 6812305023089 | Tax Free Transfer Out | ABC | 106 |
db
【讨论】:
【参考方案2】:一种方法是使用条件聚合将行“透视”到列。您知道您始终拥有相同的列,因此您只需使用 case
为每列选择值。
请注意,您的示例输出 (ID_Number) 与您的示例数据不完全匹配,假设这只是示例数据准备疏忽。
您还需要一个额外的列来将 Investor_Id 组合在一起。
select
max(case idMetadataKey when 3 then value end) Investor_Id,
max(case idMetadataKey when 5 then value end) First_Name,
max(case idMetadataKey when 1 then value end) Last_Name,
max(case idMetadataKey when 4 then value end) Id_Number,
max(case idMetadataKey when 6 then value end) Work_Description,
max(case idMetadataKey when 2 then value end) Company,
IDBatch
from (
select *, Row_Number() over(partition by idbatch, IdMetadataKey order by IdMetadata) grp
from Metadatad
)m
group by IDBatch, grp
order by IDBatch, grp
看到这个DBFiddle
【讨论】:
以上是关于根据公共列值将定义的行数转换为列的主要内容,如果未能解决你的问题,请参考以下文章