UNPIVOT 假期时间

Posted

技术标签:

【中文标题】UNPIVOT 假期时间【英文标题】:UNPIVOT Holiday Hours 【发布时间】:2020-12-09 20:00:18 【问题描述】:

我有一张桌子,可以记录商店的假日营业时间:

LOCATION_ID DATE1       TIMES1          DATE2       TIMES2
123456      2020-12-12  10:00AM-09:00PM 2020-12-19  10:00AM-09:00PM

这是一个过于简单化的表格。大约有 30 列按日期排列,包括商店营业时间 - 它继续(DATE3、TIMES3、DATE4、TIMES4 等)。

我需要对值进行垂直反转,确保日期和时间值在同一记录中。

(注意:一旦我弄清楚UNPIVOT 表达式的结构正确,我将自己使用动态SQL 来旋转列名)

期望的结果:

LOCATION_ID    DATE         TIME
123456         2020-12-12   10:00AM-09:00PM
123456         2020-12-19   10:00AM-09:00PM

我尝试使用UNPIVOT,但我被卡住了。有什么想法吗?

样本数据:

CREATE TABLE #HOURS (LOCATION_ID int, DATE1 varchar(255), TIMES1 varchar(255), DATE2 
varchar(255), TIMES2 varchar(255));

INSERT INTO #HOURS VALUES ('123456', '2020-12-12', '10:00AM-09:00PM','2020-12-19','10:00AM-09:00PM' )

我尝试过的代码:

SELECT * 
FROM   (SELECT location_id, 
               [date1], 
               [times1], 
               [date2] 
        FROM   #hours) AS cp 
       UNPIVOT ( pivotvalues 
               FOR pivvalues IN ([Date1], 
                                 [date2], 
                                 [times1]) ) AS up1 

【问题讨论】:

【参考方案1】:

戈登 100% 正确 (+1)。

但是,如果您正在寻找一种无需使用动态 SQL 的动态方法,请考虑以下事项。

示例

Select Location_ID
      ,Date  = max(case when [Item] like 'DATE%' then Value end)
      ,Time  = max(case when [Item] like 'TIME%' then Value end)
 From (
        select A.Location_ID
              ,Grp = replace(replace([Item],'DATE',''),'TIMES','')
              ,B.*
         from #hours  A
         Cross Apply [dbo].[tvf-XML-Unpivot-Row]( (Select A.* for XML RAW) ) B
         Where [Item] not in ('LOCATION_ID')
      ) A
 Group By Location_ID,Grp

退货

Location_ID   Date          Time
123456        2020-12-12    10:00AM-09:00PM
123456        2020-12-19    10:00AM-09:00PM

感兴趣的表值函数

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)
)

【讨论】:

谢谢约翰!我收到语法错误 - 是因为我们使用的是 SQL Server 2012 吗? @DepthofField 针对 XML 版本与 JSON 方法进行了更新。 @DepthofField 先应用 CREATE FUNCTION 哦,我立即接受了另一个,因为这是发布的第一个答案!事后看来,Yours 对我来说确实更好用,因为它动态处理列,并且已更新为可与 2012 年一起使用。因此更新了 :) @JohnCappelletti 。 . .您使用 XML 和 JSON 的版本总是非常聪明。【参考方案2】:

不要使用unpivot。使用apply

select h.location_id, v.date, v.time
from #hours h cross apply
     (values (h.date1, h.times1), (h.date2, h.times2)
     ) v(date, time);

unpivot 是一种非标准语法,它只做一件事。 APPLY横向连接的 SQL Server 实现。这是一个非常强大的join 类型——使用它进行反透视是开始学习语法的好方法。

【讨论】:

以上是关于UNPIVOT 假期时间的主要内容,如果未能解决你的问题,请参考以下文章

UNPIVOT 返回数据类型

将结果集从 UNPIVOT 插入到表中

聚合函数和 unpivot

PIVOT/UNPIVOT 多于一列

UnPivot 多列 MSSQLServer

交叉应用与 UNPIVOT