SQL unpivot 多列

Posted

技术标签:

【中文标题】SQL unpivot 多列【英文标题】:SQL unpivot of multiple columns 【发布时间】:2021-05-29 11:57:31 【问题描述】:

我希望以下宽表不进行透视,但仅在用户对该字段具有真实值以及适当日期的情况下进行。 当前状态:


CUSTOMER_ID First_Party_Email Third_Party_Email First_Party_Email_Date Third_Party_Email_Date
40011111 1 1 2021-01-22 04:38:00.000 2021-01-17 06:38:00.000
50022222 NULL 1 NULL 2021-01-18 04:38:00.000
80066666 1 NULL 2021-01-24 05:38:00.000 NULL
_______________ _______________________ _______________________ _______________________________ _______________________________

要求的状态:


Customer_ID Type Value Date
40011111 First_Party_Email 1 22/01/2021 04:38
40011111 Third_Party_Email 1 17/01/2021 06:38
50022222 Third_Party_Email 1 18/01/2021 04:38
80066666 First_Party_Email 1 24/01/2021 05:38
_______________________________________________________________________

创建表的关联查询和我的尝试不起作用:

create table Permissions_Obtained
(Customer_ID bigint
,First_Party_Email  bit
,Third_Party_Email  bit
,First_Party_Email_Date datetime    
,Third_Party_Email_Date datetime
)

insert into Permissions_Obtained
(Customer_ID
,First_Party_Email
,Third_Party_Email
,First_Party_Email_Date
,Third_Party_Email_Date
)
VALUES
(40011111,  1,      1,      '2021-01-22 04:38', '2021-01-17 06:38'),
(50022222,  NULL,   1,      NULL,               '2021-01-18 04:38'),
(80066666,  1,      NULL,   '2021-01-24 05:38', null)

select * 
from Permissions_Obtained

select 
customer_id, Permission
from Permissions_Obtained
unpivot
(
  GivenPermission
  for Permission in (
First_Party_Email, Third_Party_Email
)
) unpiv1, 
unpivot
(
  GivenPermissionDate
  for PermissionDate in (
First_Party_Email_Date, Third_Party_Email_Date
)
) unpiv2
where GivenPermission = 1

--drop table Permissions_Obtained

任何帮助将不胜感激。 TIA

【问题讨论】:

【参考方案1】:

您不能同时拥有多个 unpivot。相反,您可以根据您的要求使用交叉应用或内部联接或联合、联合全部或某种联接。我已经使用 join 和 unpivot 为此添加了一个示例答案。

   SELECT 
       unpvt.Customer_ID 
       , [Type]
       ,  ISNULL(po.First_Party_Email ,po.Third_Party_Email) AS [Value] 
       ,CASE WHEN unpvt.Type = 'First_Party_Email' THEN po.First_Party_Email_Date
             ELSE  po.Third_Party_Email_Date  
             END AS  [Date]

     FROM   
        (
         SELECT 
           Customer_ID, First_Party_Email , Third_Party_Email  
           FROM Permissions_Obtained 
         ) p  
       UNPIVOT  
          (  [Value] FOR [Type]     IN   
               (First_Party_Email , Third_Party_Email )  
          )AS unpvt
          INNER JOIN  Permissions_Obtained [po] 
             on [po].Customer_ID = unpvt.Customer_ID

【讨论】:

您在这里找到解决方案了吗?@DarkWolve【参考方案2】:

当取消旋转多个列时,CROSS APPLY (VALUES 通常是最简单、最有效的解决方案。

它为前一个表的每行创建一个虚拟表,因此将其取消透视到单独的行中。

SELECT
    p.Customer_Id,
    v.[Type],
    v.Value,
    v.Date
FROM Permissions_Obtained p
CROSS APPLY (VALUES
    ('First_Party_Email', p.First_Party_Email, p.First_Party_Email_Date),
    ('Third_Party_Email', p.Third_Party_Email, p.Third_Party_Email_Date)
) v([Type], Value, Date)
where v.Value IS NOT NULL;

【讨论】:

以上是关于SQL unpivot 多列的主要内容,如果未能解决你的问题,请参考以下文章

oracle unpivot 多列到多列

UnPivot 多列 MSSQLServer

PIVOT/UNPIVOT 多行多列

多列,多表列到行 unpivot

如何对具有常量/缺失列的多列使用 unpivot?

oracle 多列 列转行