以列名称为日期取消数据透视

时间:2018-11-16 14:33:40

标签: sql sql-server unpivot

我以交叉表格式包含以下数据:

prod_codigo  esps_fecini  day1    day2    day3    day4    day5  day6  day7
1077         2018-11-12   200.00  200.00  250.00  250.00  0.00  0.00  0.00
...

我需要将数据转换为如下形式:

prod_codigo  esps_fecini   Bins
1077         2018-11-12    200.00
1077         2018-11-13    200.00
1077         2018-11-14    250.00
1077         2018-11-15    250.00
1077         2018-11-16    0.00
1077         2018-11-17    0.00
1077         2018-11-18    0.00
...

我该如何实现?

我正在使用以下查询,但是找不到求和日期的方法。我正在使用SQL Server 2008

select prod_codigo,esps_fecini,U.Bins
from dba.estimprodsemana
unpivot
(
Bins
for datos in (esps_cadia1,esps_cadia2,esps_cadia3,esps_cadia4,esps_cadia5,esps_cadia6,esps_cadia7)
) U

4 个答案:

答案 0 :(得分:2)

如果您想unpivot进行此查询,则可以这样操作:

declare @t table (prod_codigo int,esps_fecini date,day1 decimal(5,2),day2 decimal(5,2),
                  day3 decimal(5,2),day4 decimal(5,2),day5 decimal(5,2),day6 decimal(5,2),
                  day7 decimal(5,2))
insert into @t(prod_codigo,esps_fecini,day1,day2,day3,day4,day5,day6,day7) values
(1077,'20181112',200.00,200.00,250.00,250.00,0.00,0.00,0.00)

select
    prod_codigo,
    newDay,
    Value
from
    @t
        unpivot
    (Value for Offset in (day1,day2,day3,day4,day5,day6,day7)) u
        cross apply
    (select DATEADD(day,CONVERT(int,SUBSTRING(Offset,4,1))-1,esps_fecini) as newDay) v

首先unpivot,然后找出如何从生成的数据中提取可用数字(而不是元数据-列名)来调整日期值。

结果:

prod_codigo newDay     Value
----------- ---------- ---------------------------------------
1077        2018-11-12 200.00
1077        2018-11-13 200.00
1077        2018-11-14 250.00
1077        2018-11-15 250.00
1077        2018-11-16 0.00
1077        2018-11-17 0.00
1077        2018-11-18 0.00

答案 1 :(得分:0)

您可以改用APPLY

select e.prod_codigo, ee.*
from dba.estimprodsemana e cross apply
     ( values (esps_fecini, day1),
              (dateadd(day, 1, esps_fecini), day2),
              (dateadd(day, 2, esps_fecini), day3),
              (dateadd(day, 3, esps_fecini), day3),
              (dateadd(day, 4, esps_fecini), day4),
              (dateadd(day, 5, esps_fecini), day5),
              (dateadd(day, 6, esps_fecini), day6),
              (dateadd(day, 7, esps_fecini), day7)
     ) ee (esps_fecini, Bins);

答案 2 :(得分:0)

您的问题中给出了答案,只需要一点格式化:)

在这种情况下,还需要基于自然顺序使用ROW_NUMBER()得出偏移量。然后,您可以根据列顺序D1..D7的应用字段来计算日期。

DECLARE @T TABLE(ID INT, Date DATETIME, D1 INT, D2 INT, D3 INT, D4 INT, D5 INT, D6 INT, D7 INT)
INSERT @T VALUES(1077,'11/12/2018',200,200,250,250,0,0,0)


SELECT
    ID,
    Date = DATEADD(DAY,DayNumber,Date),
    Bins    
FROM
(
    SELECT 
        ID,
        Date,
        Bins,
        DayNumber = ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID) - 1
    FROM @T
    UNPIVOT
    (
        Bins FOR Dates in (D1,D2,D3,D4,D5,D6,D7)
    ) AS X
)AS Y

答案 3 :(得分:0)

如果天列的数量超出了您编写或指定代码的范围,或者天列的数量可变,则以下内容将“动态地”取消透视数据,而无需实际使用动态SQL。

显然,UNPIVOT的表现会更好

示例

declare @YourTable table (prod_codigo int,esps_fecini date,day1 decimal(5,2),day2 decimal(5,2),day3 decimal(5,2),day4 decimal(5,2),day5 decimal(5,2),day6 decimal(5,2),day7 decimal(5,2))
insert into @YourTable values
(1077,'20181112',200.00,200.00,250.00,250.00,0.00,0.00,0.00)


Select A.prod_codigo
      ,esps_fecini = dateadd(day,-1+replace(Item,'day',''),esps_fecini)
      ,Bins=C.Value
 From @YourTable A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item = a.value('local-name(.)','varchar(100)')
                      ,Value = a.value('.','decimal(5,2)') 
                 From  B.XMLData.nodes('/row')  as C1(n)
                 Cross Apply C1.n.nodes('./@*') as C2(a)
                 Where a.value('local-name(.)','varchar(100)') like  'day%'
             ) C

返回

prod_codigo esps_fecini Bins
1077        2018-11-12  200.00
1077        2018-11-13  200.00
1077        2018-11-14  250.00
1077        2018-11-15  250.00
1077        2018-11-16  0.00
1077        2018-11-17  0.00
1077        2018-11-18  0.00