【问题标题】:Pivot two columns in T-SQL在 T-SQL 中旋转两列
【发布时间】:2017-09-25 18:35:52
【问题描述】:

首先 - 我已经看了两天的例子并尝试应用它们但没有成功。我不了解 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 件购买的物品。

提前致谢!

【问题讨论】:

    标签: sql sql-server tsql pivot


    【解决方案1】:

    由于您不需要动态并在 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
    

    返回

    应要求 - 一些评论

    这是一个简单的条件聚合,有点扭曲。扭曲是使用窗口函数 Row_Number() 的子查询。子查询生成以下内容:

    注意最后一列RN。您可能会看到它是由Location, Mgr, CId, CName, BDate, Age 分区并由Item,PDate 排序的增量YET

    一旦子查询被解决(使用 RN),我们就可以应用最终的聚合,它本质上是一个枢轴

    窗口函数非常宝贵,值得您花时间熟悉它们,

    【讨论】:

    • 谢谢@John Cappelletti。
    • @Talay 很高兴它有帮助
    • 感谢@JohnCappelletti。这解决了我的问题。非常感激。您介意解释一下 SQL 的 [Item]/[Date] 行中发生了什么吗?我从来没有使用过这样的构造,虽然它就像我需要的那样工作,但我真的很想了解发生了什么——尤其是使用 [Item] [Date] 语法;和 Max() 语法。 ......如果你有时间/倾向。格雷西!
    • @Talay 当然,我稍后会添加一些评论
    • @Talay 添加了一些 cmets
    【解决方案2】:

    我玩过,这就是我想出的。约翰的效率更高。

    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
    

    【讨论】:

    • 谢谢@Jason!感谢您的意见。
    猜你喜欢
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2022-01-12
    • 1970-01-01
    • 2012-05-08
    相关资源
    最近更新 更多