SQL 服务器高级数据透视分组行到列
SQL Server advanced Pivot grouped rows to columns
我需要 Pivot/rotate 将行中的数据转换为列 - 但与我见过的大多数示例略有不同。
我们有客户会成套购买东西(想想比萨配料卖家......人们总是会购买奶酪、面团和酱汁;有些人可能会购买配料,但我们不关心这些)。
我需要做的是将此行数据按订单日期排序到列中。下面是两个脚本来填充临时输入和临时输出 table 以显示我正在尝试实现的目标。
SQL 服务器 2008
CREATE table #myInput
(CustomerID Varchar(10), OrderDate varchar(10), Item varchar(13), ItemColor varchar(20));
CREATE table #myOUTPUT
(
CustomerID Varchar(10),
OrderDate_1 varchar(10),
PartA_1 varchar(20),
PartB_1 varchar(20),
PartC_1 varchar(20),
OrderDate_2 varchar(10),
PartA_2 varchar(20),
PartB_2 varchar(20),
PartC_2 varchar(20),
OrderDate_3 varchar(10),
PartA_3 varchar(20),
PartB_3 varchar(20),
PartC_3 varchar(20)
)
INSERT INTO #myInput
(CustomerID, OrderDate, Item, ItemColor)
VALUES
('abc','5/1/2001','PartA','Silver'),
('abc','5/1/2001','PartB','Red'),
('abc','5/1/2001','PartC','Green'),
('abc','5/20/2002','PartA','Purple'),
('abc','5/20/2002','PartB','Yellow'),
('abc','5/20/2002','PartC','Black'),
('abc','10/1/2002','PartA','Red'),
('abc','10/1/2002','PartB','Silver'),
('abc','10/1/2002','PartC','Blue'),
('def','4/1/2000','PartA','Green'),
('def','4/1/2000','PartB','Red'),
('def','4/1/2000','PartC','White'),
('jkl','5/1/2001','PartA','Black'),
('jkl','5/1/2001','PartB','Yellow'),
('jkl','5/1/2001','PartC','Silver'),
('jkl','10/10/2001','PartA','Green'),
('jkl','10/10/2001','PartB','Black'),
('jkl','10/10/2001','PartC','Silver')
;
结果:
insert into #myOUTPUT
(CustomerID,OrderDate_1,PartA_1,PartB_1,PartC_1,OrderDate_2,PartA_2,PartB_2, PartC_2,OrderDate_3,PartA_3,PartB_3,PartC_3)
VALUES
('abc','5/1/2001','Silver','Red','Green','5/20/2002','Purple','Yellow','Black','10/1/2002','Red','Silver','Blue'),
('def','4/1/2000','Green','Red','White','','','','','','','',''),
('jkl','5/1/2001','Black','Yellow','Silver','10/10/2001','Green','Black','Silver','','','','');
select * from #myInput
select * from #myOUTPUT
我们正在寻找 17 个或更少的订单。至少在目前,我们没有为任何一位客户接到超过一打的订单。
我尝试了几种不同的方法 - pivot 似乎没有产生我正在寻找的输出。我在想也许 dense_rank 来确定我们首先需要多少列,然后通过 cte 插入到游标句柄中?但我无法准确获得所需的输出。请注意,源 "date" 字段作为 varchar 存储在数据库中。此外,没有订单号 - 因此唯一性仅来自客户 ID 和日期。
我会使用条件聚合来解决这个问题。如果我理解正确的话:
select customer,
max(case when seqnum_co = 1 then orderdate end) as orderdate_1,
max(case when seqnum_co = 1 and item = 'Part_A' then itemcolor end) as parta_1,
max(case when seqnum_co = 1 and item = 'Part_B' then itemcolor end) as partb_1,
max(case when seqnum_co = 1 and item = 'Part_C' then itemcolor end) as partc_1,
max(case when seqnum_co = 2 then orderdate end) as orderdate_2,
max(case when seqnum_co = 2 and item = 'Part_A' then itemcolor end) as parta_2,
max(case when seqnum_co = 2 and item = 'Part_B' then itemcolor end) as partb_2,
max(case when seqnum_co = 2 and item = 'Part_C' then itemcolor end) as partc_2,
. . .
from (select i.*,
dense_rank() over (partition by i.customerid order by orderdate) as seqnum_co
from #myinput
) i
group by customer;
我需要 Pivot/rotate 将行中的数据转换为列 - 但与我见过的大多数示例略有不同。
我们有客户会成套购买东西(想想比萨配料卖家......人们总是会购买奶酪、面团和酱汁;有些人可能会购买配料,但我们不关心这些)。
我需要做的是将此行数据按订单日期排序到列中。下面是两个脚本来填充临时输入和临时输出 table 以显示我正在尝试实现的目标。
SQL 服务器 2008
CREATE table #myInput
(CustomerID Varchar(10), OrderDate varchar(10), Item varchar(13), ItemColor varchar(20));
CREATE table #myOUTPUT
(
CustomerID Varchar(10),
OrderDate_1 varchar(10),
PartA_1 varchar(20),
PartB_1 varchar(20),
PartC_1 varchar(20),
OrderDate_2 varchar(10),
PartA_2 varchar(20),
PartB_2 varchar(20),
PartC_2 varchar(20),
OrderDate_3 varchar(10),
PartA_3 varchar(20),
PartB_3 varchar(20),
PartC_3 varchar(20)
)
INSERT INTO #myInput
(CustomerID, OrderDate, Item, ItemColor)
VALUES
('abc','5/1/2001','PartA','Silver'),
('abc','5/1/2001','PartB','Red'),
('abc','5/1/2001','PartC','Green'),
('abc','5/20/2002','PartA','Purple'),
('abc','5/20/2002','PartB','Yellow'),
('abc','5/20/2002','PartC','Black'),
('abc','10/1/2002','PartA','Red'),
('abc','10/1/2002','PartB','Silver'),
('abc','10/1/2002','PartC','Blue'),
('def','4/1/2000','PartA','Green'),
('def','4/1/2000','PartB','Red'),
('def','4/1/2000','PartC','White'),
('jkl','5/1/2001','PartA','Black'),
('jkl','5/1/2001','PartB','Yellow'),
('jkl','5/1/2001','PartC','Silver'),
('jkl','10/10/2001','PartA','Green'),
('jkl','10/10/2001','PartB','Black'),
('jkl','10/10/2001','PartC','Silver')
;
结果:
insert into #myOUTPUT
(CustomerID,OrderDate_1,PartA_1,PartB_1,PartC_1,OrderDate_2,PartA_2,PartB_2, PartC_2,OrderDate_3,PartA_3,PartB_3,PartC_3)
VALUES
('abc','5/1/2001','Silver','Red','Green','5/20/2002','Purple','Yellow','Black','10/1/2002','Red','Silver','Blue'),
('def','4/1/2000','Green','Red','White','','','','','','','',''),
('jkl','5/1/2001','Black','Yellow','Silver','10/10/2001','Green','Black','Silver','','','','');
select * from #myInput
select * from #myOUTPUT
我们正在寻找 17 个或更少的订单。至少在目前,我们没有为任何一位客户接到超过一打的订单。
我尝试了几种不同的方法 - pivot 似乎没有产生我正在寻找的输出。我在想也许 dense_rank 来确定我们首先需要多少列,然后通过 cte 插入到游标句柄中?但我无法准确获得所需的输出。请注意,源 "date" 字段作为 varchar 存储在数据库中。此外,没有订单号 - 因此唯一性仅来自客户 ID 和日期。
我会使用条件聚合来解决这个问题。如果我理解正确的话:
select customer,
max(case when seqnum_co = 1 then orderdate end) as orderdate_1,
max(case when seqnum_co = 1 and item = 'Part_A' then itemcolor end) as parta_1,
max(case when seqnum_co = 1 and item = 'Part_B' then itemcolor end) as partb_1,
max(case when seqnum_co = 1 and item = 'Part_C' then itemcolor end) as partc_1,
max(case when seqnum_co = 2 then orderdate end) as orderdate_2,
max(case when seqnum_co = 2 and item = 'Part_A' then itemcolor end) as parta_2,
max(case when seqnum_co = 2 and item = 'Part_B' then itemcolor end) as partb_2,
max(case when seqnum_co = 2 and item = 'Part_C' then itemcolor end) as partc_2,
. . .
from (select i.*,
dense_rank() over (partition by i.customerid order by orderdate) as seqnum_co
from #myinput
) i
group by customer;