根据公共列值将定义的行数转换为列

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

dbhere

【讨论】:

【参考方案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

【讨论】:

以上是关于根据公共列值将定义的行数转换为列的主要内容,如果未能解决你的问题,请参考以下文章

将未定义的行数转置为列

如何根据数据框中的列值获取特定的行数[重复]

如何根据 azure databricks 中的列值将静态值传递给动态值

如何在sql中将行转换为列

如何在 SQL 中将行转换为列值 [关闭]

根据另一个表中的列值选择一个表中的行?