UNPIVOT 假期时间

UNPIVOT Holiday Hours

我有一个 table,可以跟踪商店假期营业时间:

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

这是一个高度简化的 table。大约有 30 列按日期水平排列的商店营业时间 - 它继续(DATE3、TIMES3、DATE4、TIMES4 等)。

我需要垂直反转值,确保日期和时间值在同一条记录上。

(注意:一旦我想出正确构造 UNPIVOT 表达式,我将自己使用 Dynamic 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 

不要使用 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 服务器实现。这是一个非常强大的 join 类型——用它来逆透视是开始学习语法的好方法。

戈登 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

Returns

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

Table-值函数如果感兴趣

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