以列名作为日期的逆透视
Unpivot with column name as date
我有以下交叉表格式的数据:
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
您可以使用 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);
你的问题已经有了答案,只是稍微格式化一下:)
此外,在这种情况下,您需要根据自然顺序使用 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
如果你想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
如果您的天数列多于您想要编码或指定的数量,或者如果天数列的数量是可变的,则以下将 "dynamically" 逆透视您的数据而不实际使用动态 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
Returns
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
我有以下交叉表格式的数据:
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
您可以使用 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);
你的问题已经有了答案,只是稍微格式化一下:)
此外,在这种情况下,您需要根据自然顺序使用 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
如果你想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
如果您的天数列多于您想要编码或指定的数量,或者如果天数列的数量是可变的,则以下将 "dynamically" 逆透视您的数据而不实际使用动态 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
Returns
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