【问题标题】:SQL Pivot select multiple rowsSQL Pivot 选择多行
【发布时间】:2018-08-30 07:12:45
【问题描述】:

这是我的桌子:

我想像这样创建枢轴:

我写了一些查询,但我只得到对角线的名字:

(
select 
[1] as Client0, 
[2] as Client1, 
[3] as Client2, 
[4] as Client3,
[5] as Client4
from 
(
select 
    rc.DateCreated, 
    gd.Name,
    DENSE_RANK() over (order by gd.ID_TableGD) as colnum
from TableGD gd
inner join TableRC rc ON gd.ID_TableGD = rc.ID_TableRC
WHERE gd.ID_TableGD IN (962,1029,1024) 
AND gd.Active = 1
) as t
pivot
(
MAX(Name)
for colnum in 
(
[1],
[2],
[3],
[4],
[5]

)
) as pvt) 

所以,我希望特定客户能够在同一列中获取 clientName (ClientA) 和 CreatedDate。

这是我的第一个支点,我不确定是否需要输入 Max(Name)?

我得到这样的表格:

【问题讨论】:

    标签: sql sql-server tsql pivot unpivot


    【解决方案1】:

    我会使用 CROSS APPLYValue 来做到这一点。

    首先,您需要执行unpivot 以让您的DateCreatedName 在一个列中,这来自您的预期结果。

    让结果看起来像这样。

    SELECT 
      v.*
    FROM T t1 CROSS APPLY(
        VALUES 
        (Name,colnum,1),
        (CAST(DateCreated AS VARCHAR(50)),colnum,2)
    ) v (val,colnum,grp)
    

    结果

    |        val | colnum | grp |
    |------------|--------|-----|
    |    ClientA |      1 |   1 |
    | 2018-08-21 |      1 |   2 |
    |    ClientB |      2 |   1 |
    | 2018-08-22 |      2 |   2 |
    |    ClientC |      3 |   1 |
    | 2018-08-23 |      3 |   2 |
    

    下一步你可以尝试使用Pivot让垂直数据变为水平数据。

    CREATE TABLE T(
       Name VARCHAR(50),
       DateCreated DATE,
       colnum INT
    );
    INSERT INTO T VALUES('ClientA','2018-08-21',1);
    INSERT INTO T VALUES('ClientB','2018-08-22',2);
    INSERT INTO T VALUES('ClientC','2018-08-23',3);
    

    查询 1

    SELECT 
        MAX(CASE WHEN v.colnum = 1 THEN v.val end) client0,
        MAX(CASE WHEN v.colnum = 2 THEN v.val end) client1,
        MAX(CASE WHEN v.colnum = 3 THEN v.val end) client2,
        MAX(CASE WHEN v.colnum = 4 THEN v.val end) client3,
        MAX(CASE WHEN v.colnum = 5 THEN v.val end) client4
    FROM T t1 CROSS APPLY(
        VALUES 
        (Name,colnum,1),
        (CAST(DateCreated AS VARCHAR(50)),colnum,2)
    ) v (val,colnum,grp)
    group by grp
    

    Results

    |    client0 |    client1 |    client2 | client3 | client4 |
    |------------|------------|------------|---------|---------|
    |    ClientA |    ClientB |    ClientC |  (null) |  (null) |
    | 2018-08-21 | 2018-08-22 | 2018-08-23 |  (null) |  (null) |
    

    CROSS APPLY ... Value

    注意

    如果你想显示你原来的日期时间格式。

    您可以使用CONVERTFORMAT 来转换您期望的日期时间格式。

    此示例适用于 FORMAT http://sqlfiddle.com/#!18/12ae9e/3

    虽然formatConvert使用起来更简单,但在处理多数据时性能较差。

    【讨论】:

    • 你能给我一个例子吗?谢谢
    • @Stefan0309 好的,请稍等,我添加一些解释。
    • @Stefan0309 我为你补充一些解释
    • 优秀。有用!只有当它将日期转换为 nvarchar 时,我才会得到不同的格式,例如:2018 年 8 月 21 日下午 4:41 我可以在 nvarchar 中保留 sql 日期格式,例如:2018-08-21 16:41:00 吗?
    • 您可以使用CONVERT FORMAT来转换您期望的日期时间格式。此示例适用于 FORMAT sqlfiddle.com/#!18/12ae9e/3
    【解决方案2】:

    使用 max in time 如下所示:

    select 
    max([1]) as Client0, 
    max([2]) as Client1, 
    max([3]) as Client2, 
    max([4]) as Client3,
    max([5]) as Client4
    from 
    (
    select 
        rc.DateCreated, 
        gd.Name,
        DENSE_RANK() over (order by gd.ID_TableGD) as colnum
    from TableGD gd
    inner join TableRC rc ON gd.ID_TableGD = rc.ID_TableRC
    WHERE gd.ID_TableGD IN (962,1029,1024) 
    AND gd.Active = 1
    ) as t
    pivot
    (
    MAX(Name)
    for colnum in 
    (
    [1],
    [2],
    [3],
    [4],
    [5]
    
    )
    ) as pvt
    

    【讨论】:

    • 现在我只有一行很棒,但我仍然需要 datecreated 行,就在名称行的下方
    • 对 union all 做同样的事情——它会给你想要的结果
    • 它给了我一个错误,用于转换“从字符串转换日期和/或时间时转换失败。”我需要在哪里投射?枢轴中的列? @fa06
    猜你喜欢
    • 1970-01-01
    • 2011-08-28
    • 2011-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多