SQL 多个 rows/records 成一行 3 列

SQL Multiple rows/records into one row with 3 columns

我有一个与此虚拟数据类似的 table,其中一个人有 3 条记录。我想将其更改为包含多列的一条记录。对我来说最复杂的是我想要基于 Date_Purchased

的 3 个最新产品

现有:

姓名名字姓氏 MbrKey 产品购买日期
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 产品 A 3/1/2015
简·琼斯 555555 ProductA 1/1/2015
简·琼斯 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 

我认为这让我更接近了,因为结果如下:

姓名名字姓氏 MbrKey Product1 Product2 Product3 
Doe John 123456 ProductB NULL NULL
Doe John 123456 NULL ProductA NULL
Doe John 123456 NULL NULL 产品A
Jones Jane 555555 ProductA NULL NULL
琼斯简 555555 NULL ProductB NULL
史密斯·乔 987654 ProductA NULL NULL

未来的状态:下面是我所希望的。

姓名名字姓氏 MbrKey Product1 Product2 Product3 
Doe John 123456 产品 B 产品 B 产品 A
Jones Jane 555555 ProductA ProductB Null
史密斯·乔 987654 ProductA Null Null

如有任何帮助,我们将不胜感激!

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

给你:

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() 函数就不必作用于所有记录。此外,如果您有一个成员 table,您可以使用它来代替本例中的 "Members" 子查询。

尝试 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分区。我留给你。