在 T-SQL 中旋转两列
Pivot two columns in T-SQL
首先 - 我已经看了两天示例并尝试应用它们但没有成功。我不了解 Pivot 的工作机制,希望能得到一些帮助。
我有一个数据集,每个客户有多行 - 每次购买一行。
我想为每个客户获取一行 - 最多 6 次购买以及每次的购买日期。
老实说,我什至不知道这是否可能...因为购买日期 [PDate] 可能相差很大。 ?
这是我的起始数据集 SQL:
DECLARE @Test AS TABLE
(
Location VARCHAR(20),
Mgr VARCHAR(30),
CId VARCHAR(20),
CName VARCHAR(100),
BDate DATE,
Age Int,
Item Varchar(15),
PDate Date
)
Insert Into @Test
(Location, Mgr, CId, CName, BDate, Age, Item, PDate)
Values
('A','Bob','1','Bill Jones','1967-04-27', 50,'Hammer','2017-04-05'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Nails','2017-03-17'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Screws','2017-02-15'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Nails','2017-01-26'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Screws','2016-12-20'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Nails','2016-11-03'),
('B','Dan','15','Sharon Jones','1969-04-27', 48,'Nails','2017-04-05'),
('B','Dan','15','Sharon Jones','1969-04-27', 48,'Nails','2017-03-07'),
('B','Dan','15','Sharon Jones','1969-04-27', 48,'Screws','2017-02-18')
Select * From @Test
我需要看这个:
A Bob 1 Bill Jones 1967-04-27 50 Hammer 2017-04-05 Nails 2017-03-17 ....
B Dan 15 Sharon Jones 1969-04-27 48 Nails 2017-04-05 Nails 2017-03-07 ....
...本质上,每个 CId 一行:
位置、经理、CId、CName、BDate、年龄、Item1、Date1、Item2、Date2、Item3、Date3
... 最多购买 6 件商品。
提前致谢!
由于您不需要动态化并在 6 时达到最大值,简单的条件聚合就可以了。
Select Location, Mgr, CId, CName, BDate, Age
,[Item1] = max(case when RN=1 then Item end)
,[Date1] = max(case when RN=1 then Pdate end)
,[Item2] = max(case when RN=2 then Item end)
,[Date2] = max(case when RN=2 then Pdate end)
,[Item3] = max(case when RN=3 then Item end)
,[Date3] = max(case when RN=3 then Pdate end)
,[Item4] = max(case when RN=4 then Item end)
,[Date4] = max(case when RN=4 then Pdate end)
,[Item5] = max(case when RN=5 then Item end)
,[Date5] = max(case when RN=5 then Pdate end)
,[Item6] = max(case when RN=6 then Item end)
,[Date6] = max(case when RN=6 then Pdate end)
From (
Select *
,RN = Row_Number() over (Partition By Location, Mgr, CId, CName, BDate, Age Order by Item,PDate)
From Test
) A
Group By Location, Mgr, CId, CName, BDate, Age
Returns
As Requested - Some Commentary
这是一个简单的条件聚合,略有改动。扭曲是使用 window 函数 Row_Number() 的子查询。子查询生成以下内容:
注意最后一列 RN
。您可能会看到它是按 Location, Mgr, CId, CName, BDate, Age
分区并按 Item,PDate
排序的增量 YET
一旦子查询被取消(使用 RN),我们就可以应用最终的聚合,它本质上是一个数据透视表
window 功能非常宝贵,值得您花时间熟悉它们,
我试了一下,这就是我想出的。约翰的效率更高。
WITH preSelect AS
(Select ROW_NUMBER() OVER(PARTITION BY Location,Mgr,CId,CName,BDate,Age
ORDER BY LOCATION) 'rowNum',
Location,Mgr,CId,CName,BDate,Age,Item,PDate
From @Test)
Select t.Location,t.Mgr,t.CId,t.CName,t.BDate,t.Age,
t1.Item 'Item 1',t1.PDate 'Date 1',
t2.Item 'Item 2',t2.PDate 'Date 2',
t3.Item 'Item 3',t3.PDate 'Date 3',
t4.Item 'Item 4',t4.PDate 'Date 4',
t5.Item 'Item 5',t5.PDate 'Date 5',
t6.Item 'Item 6',t6.PDate 'Date 6'
From @Test t
LEFT JOIN preSelect t1 ON t.Location = t1.Location AND t1.rowNum = 1
LEFT JOIN preSelect t2 ON t.Location = t2.Location AND t2.rowNum = 2
LEFT JOIN preSelect t3 ON t.Location = t3.Location AND t3.rowNum = 3
LEFT JOIN preSelect t4 ON t.Location = t4.Location AND t4.rowNum = 4
LEFT JOIN preSelect t5 ON t.Location = t5.Location AND t5.rowNum = 5
LEFT JOIN preSelect t6 ON t.Location = t6.Location AND t6.rowNum = 6
GROUP BY t.Location,t.Mgr,t.CId,t.CName,t.BDate,t.Age,
t1.Item,t1.PDate,t2.Item,t2.PDate,t3.Item,t3.PDate,t4.Item,t4.PDate,t5.Item,t5.PDate,t6.Item,t6.PDate
首先 - 我已经看了两天示例并尝试应用它们但没有成功。我不了解 Pivot 的工作机制,希望能得到一些帮助。
我有一个数据集,每个客户有多行 - 每次购买一行。 我想为每个客户获取一行 - 最多 6 次购买以及每次的购买日期。
老实说,我什至不知道这是否可能...因为购买日期 [PDate] 可能相差很大。 ?
这是我的起始数据集 SQL:
DECLARE @Test AS TABLE
(
Location VARCHAR(20),
Mgr VARCHAR(30),
CId VARCHAR(20),
CName VARCHAR(100),
BDate DATE,
Age Int,
Item Varchar(15),
PDate Date
)
Insert Into @Test
(Location, Mgr, CId, CName, BDate, Age, Item, PDate)
Values
('A','Bob','1','Bill Jones','1967-04-27', 50,'Hammer','2017-04-05'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Nails','2017-03-17'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Screws','2017-02-15'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Nails','2017-01-26'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Screws','2016-12-20'),
('A','Bob','1','Bill Jones','1967-04-27', 50,'Nails','2016-11-03'),
('B','Dan','15','Sharon Jones','1969-04-27', 48,'Nails','2017-04-05'),
('B','Dan','15','Sharon Jones','1969-04-27', 48,'Nails','2017-03-07'),
('B','Dan','15','Sharon Jones','1969-04-27', 48,'Screws','2017-02-18')
Select * From @Test
我需要看这个:
A Bob 1 Bill Jones 1967-04-27 50 Hammer 2017-04-05 Nails 2017-03-17 ....
B Dan 15 Sharon Jones 1969-04-27 48 Nails 2017-04-05 Nails 2017-03-07 ....
...本质上,每个 CId 一行: 位置、经理、CId、CName、BDate、年龄、Item1、Date1、Item2、Date2、Item3、Date3 ... 最多购买 6 件商品。
提前致谢!
由于您不需要动态化并在 6 时达到最大值,简单的条件聚合就可以了。
Select Location, Mgr, CId, CName, BDate, Age
,[Item1] = max(case when RN=1 then Item end)
,[Date1] = max(case when RN=1 then Pdate end)
,[Item2] = max(case when RN=2 then Item end)
,[Date2] = max(case when RN=2 then Pdate end)
,[Item3] = max(case when RN=3 then Item end)
,[Date3] = max(case when RN=3 then Pdate end)
,[Item4] = max(case when RN=4 then Item end)
,[Date4] = max(case when RN=4 then Pdate end)
,[Item5] = max(case when RN=5 then Item end)
,[Date5] = max(case when RN=5 then Pdate end)
,[Item6] = max(case when RN=6 then Item end)
,[Date6] = max(case when RN=6 then Pdate end)
From (
Select *
,RN = Row_Number() over (Partition By Location, Mgr, CId, CName, BDate, Age Order by Item,PDate)
From Test
) A
Group By Location, Mgr, CId, CName, BDate, Age
Returns
As Requested - Some Commentary
这是一个简单的条件聚合,略有改动。扭曲是使用 window 函数 Row_Number() 的子查询。子查询生成以下内容:
注意最后一列 RN
。您可能会看到它是按 Location, Mgr, CId, CName, BDate, Age
分区并按 Item,PDate
一旦子查询被取消(使用 RN),我们就可以应用最终的聚合,它本质上是一个数据透视表
window 功能非常宝贵,值得您花时间熟悉它们,
我试了一下,这就是我想出的。约翰的效率更高。
WITH preSelect AS
(Select ROW_NUMBER() OVER(PARTITION BY Location,Mgr,CId,CName,BDate,Age
ORDER BY LOCATION) 'rowNum',
Location,Mgr,CId,CName,BDate,Age,Item,PDate
From @Test)
Select t.Location,t.Mgr,t.CId,t.CName,t.BDate,t.Age,
t1.Item 'Item 1',t1.PDate 'Date 1',
t2.Item 'Item 2',t2.PDate 'Date 2',
t3.Item 'Item 3',t3.PDate 'Date 3',
t4.Item 'Item 4',t4.PDate 'Date 4',
t5.Item 'Item 5',t5.PDate 'Date 5',
t6.Item 'Item 6',t6.PDate 'Date 6'
From @Test t
LEFT JOIN preSelect t1 ON t.Location = t1.Location AND t1.rowNum = 1
LEFT JOIN preSelect t2 ON t.Location = t2.Location AND t2.rowNum = 2
LEFT JOIN preSelect t3 ON t.Location = t3.Location AND t3.rowNum = 3
LEFT JOIN preSelect t4 ON t.Location = t4.Location AND t4.rowNum = 4
LEFT JOIN preSelect t5 ON t.Location = t5.Location AND t5.rowNum = 5
LEFT JOIN preSelect t6 ON t.Location = t6.Location AND t6.rowNum = 6
GROUP BY t.Location,t.Mgr,t.CId,t.CName,t.BDate,t.Age,
t1.Item,t1.PDate,t2.Item,t2.PDate,t3.Item,t3.PDate,t4.Item,t4.PDate,t5.Item,t5.PDate,t6.Item,t6.PDate