我有一个与这个虚拟数据类似的表,其中一个人有3条记录。我想将其更改为包含多列的一条记录。让我最困难的是我希望基于Date_Purchased的3个最新产品
现有:
NameFirst NameLast MbrKey Product DatePurchased John Doe 123456 ProductA 1/1/2015 John Doe 123456 ProductA 2/1/2015 John Doe 123456 ProductB 3/1/2015 John Doe 123456 ProductB 12/1/2015 Joe Smith 987654 ProductA 3/1/2015 Jane Jones 555555 ProductA 1/1/2015 Jane Jones 555555 ProductB 1/1/2015
这是我到目前为止所做的:
select MbrKey, NameLast, NameFirst,
Case when rn = 1 then Product else null end as Product1,
case when rn = 2 then Product else null end as Product2,
case when rn = 3 then Product else null end as Product3
from
(select t2.*
from(
select t.*, ROW_NUMBER () over (partition by t.MbrKey
order by t.MbrKey, t.DatePurchased desc) as RN
from testing t) as t2
where t2.RN between 1 and 3) as t3
我认为这让我更接近,因为结果如下:
NameFirst NameLast MbrKey Product1 Product2 Product3 Doe John 123456 ProductB NULL NULL Doe John 123456 NULL ProductA NULL Doe John 123456 NULL NULL ProductA Jones Jane 555555 ProductA NULL NULL Jones Jane 555555 NULL ProductB NULL Smith Joe 987654 ProductA NULL NULL
未来状态:以下是我所希望的。
NameFirst NameLast MbrKey Product1 Product2 Product3 Doe John 123456 ProductB ProductB ProductA Jones Jane 555555 ProductA ProductB Null Smith Joe 987654 ProductA Null Null
非常感谢任何帮助!
答案 0 :(得分:2)
将max()
聚合函数与case语句和group by
子句一起使用。您还可以跳过一定级别的子查询:
select
MbrKey, NameLast, NameFirst,
max(Case when rn = 1 then Product else null end) as Product1,
max(case when rn = 2 then Product else null end) as Product2,
max(case when rn = 3 then Product else null end) as Product3
from (
select
t.*,
rn = ROW_NUMBER () over (partition by t.MbrKey order by t.MbrKey, t.DatePurchased desc)
from testing t
) as t1
where t1.RN between 1 and 3
group by MbrKey, NameLast, NameFirst
答案 1 :(得分:1)
你走了:
DECLARE @Table TABLE
(
NameFirst VARCHAR(50)
,NameLast VARCHAR(50)
,MbrKey INT
,Product VARCHAR(50)
,DatePurchased DATETIME
)
INSERT INTO @Table
VALUES
('John' ,'Doe' ,123456 ,'ProductA' ,'1/1/2015' )
,('John' ,'Doe' ,123456 ,'ProductA' ,'2/1/2015' )
,('John' ,'Doe' ,123456 ,'ProductB' ,'3/1/2015' )
,('John' ,'Doe' ,123456 ,'ProductB' ,'12/1/2015')
,('Joe' ,'Smith' ,987654 ,'ProductA' ,'3/1/2015' )
,('Jane' ,'Jones' ,555555 ,'ProductA' ,'1/1/2015' )
,('Jane' ,'Jones' ,555555 ,'ProductB' ,'1/1/2015' )
SELECT
NameFirst
,NameLast
,MbrKey
,MAX(CASE ProductRank WHEN 1 THEN Product END) Product1
,MAX(CASE ProductRank WHEN 2 THEN Product END) Product2
,MAX(CASE ProductRank WHEN 3 THEN Product END) Product3
FROM
(
SELECT
MbrKey
,MAX(NameFirst) AS NameFirst
,MAX(NameLast) AS NameLast
FROM
@Table
GROUP BY MbrKey
) Members
CROSS APPLY
(
SELECT TOP 3
Product
,ROW_NUMBER() OVER (ORDER BY DatePurchased DESC) AS ProductRank
FROM @Table T
WHERE T.MbrKey = Members.MbrKey
ORDER BY DatePurchased DESC
) Products
GROUP BY
Members.MbrKey
,Members.NameFirst
,Members.NameLast
编辑:在这种情况下,使用交叉应用应该比子查询方法更好地执行,因为您只需要最新的三个产品。这样,Row_Number()函数就不必对所有记录起作用。此外,如果您有成员表,则可以使用该表而不是此示例中的“成员”子查询。
答案 2 :(得分:1)
尝试PIVOT
:
DECLARE @t TABLE
(
Name NVARCHAR(MAX) ,
Product NVARCHAR(MAX) ,
Date DATE
)
INSERT INTO @t
VALUES ( 'John', 'ProductA', '20150101' ),
( 'John', 'ProductA', '20150102' ),
( 'John', 'ProductB', '20150103' ),
( 'John', 'ProductB', '20150112' ),
( 'Joe', 'ProductA', '20150103' ),
( 'Jane', 'ProductA', '20150101' ),
( 'Jane', 'ProductB', '20150101' );
WITH cte
AS ( SELECT Name ,
Product ,
ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Date DESC ) AS RN
FROM @t
)
SELECT Name ,
[1] AS Product1 ,
[2] AS Product2 ,
[3] AS Product3
FROM cte PIVOT( MAX(Product) FOR rn IN ( [1], [2], [3] ) ) a
ORDER BY Name
输出:
Name Product1 Product2 Product3
Jane ProductA ProductB NULL
Joe ProductA NULL NULL
John ProductB ProductB ProductA
当然你应该在MbrKey
分区。我留给你。