如何将 SQL 中的列中的值 PIVOT 到新的列名中,然后在这些 PIVOT 列下列出其他列值?

Posted

技术标签:

【中文标题】如何将 SQL 中的列中的值 PIVOT 到新的列名中,然后在这些 PIVOT 列下列出其他列值?【英文标题】:How can I PIVOT the values in a column in SQL into new column names and then list other column values under these PIVOT columns? 【发布时间】:2016-06-02 11:40:03 【问题描述】:

我有一个包含 3 列的表,其中第一列是标识符,另外两列包含链接到第一列中的值的数据,如下所示:

ID |   CutOff   | Value
-------------------------------------
01 | 2016-03-31 | AA
01 | 2016-04-30 | AB
01 | 2016-05-31 | AC
02 | 2016-03-31 | BA
02 | 2016-04-30 | BB
02 | 2016-05-31 | BC
03 | 2016-03-31 | FA
03 | 2016-04-30 | FB
03 | 2016-05-31 | FC

我需要将第一列 DISTINCT 值转换为列名,但在相应的 PIVOTed 列下维护另外两列(CutOff 和 Value)中的信息。所有 ID 的截止日期都相同,但“值”列中的值对于每个 ID 都是唯一的,这是所需的结果:

CutOff     | 01 | 02 | 03 |
---------------------
2016-03-31 | AA | BA | FA
2016-04-30 | AB | BB | FB
2016-05-31 | AC | BC | FC

我在 StackExchange 上搜索和搜索了几个小时都没有到达那里,谁能提供帮助?

【问题讨论】:

标记使用的 dbms,答案可能因产品而异! 是 IDs 变量.. 即 04, 05 .. 在这种情况下,以这种方式制作表结构并不是一个好主意.. 如果它是固定的并且永远不会改变,您可以使用 group by 语句等等。 ID 确实是可变的,您可能是对的,这不是构建表格的最佳方式.. 【参考方案1】:

您可以使用条件聚合来做到这一点:

select cutoff,
       max(case when id = '01' then value end) as id_01,
       max(case when id = '02' then value end) as id_02,
       max(case when id = '03' then value end) as id_03
from t
group by cutoff
order by cutoff;

这是 ANSI 标准语法,任何数据库都支持。

【讨论】:

【参考方案2】:

如果IDs 受到限制,您可以尝试使用条件聚合:

select CutOff,
       max(case when od = '01' then Value end) as [01],
       max(case when od = '02' then Value end) as [02],
       max(case when od = '03' then Value end) as [03]
from tablename
group by CutOff   

对于SQL Server,您可以使用原生PIVOT 语句:

select CutOff, [01], [02], [03]
from tablename
pivot(max(value) for id in([01], [02], [03])) p

【讨论】:

【参考方案3】:

感谢您的帮助,我终于在 SE 上的类似线程中找到了一种方法:

    DECLARE @cols AS NVARCHAR(MAX);
    DECLARE @query AS NVARCHAR(MAX);

    SELECT @cols = STUFF((SELECT distinct ',' +
                            QUOTENAME(ID)
                          FROM MyTable
                          WHERE SomeWhereClause
                          FOR XML PATH(''), TYPE
                          ).value('.', 'NVARCHAR(MAX)') 
                          , 1, 1, '');

    SELECT @query =

    'SELECT *
    FROM
    (
      SELECT
        o.CutOff,
        p.ID,
        o.Value
      FROM MyTable AS o
      INNER JOIN OtherTableWithID AS p ON o.ID = p.ID
    ) AS t
    PIVOT 
    (
      MAX(Value) 
      FOR Value IN( ' + @cols + ' )' +
    ' ) AS p ; ';

     execute(@query);

【讨论】:

你不需要MAX(Value) FOR ID IN ( ' + @cols + ' )'

以上是关于如何将 SQL 中的列中的值 PIVOT 到新的列名中,然后在这些 PIVOT 列下列出其他列值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 BigQuery 的标准 SQL 中解析具有不同日期字符串的列中的值

如果另一列中的值是唯一的,那么如何在SQL中放置一个显示1的列,如果它是重复的则为0?

SQL中PIVOT 行列转换

如何创建临时表或仅从循环中的列中选择不同的值

如何将约束添加到 MYSQL 中的列仅以保存已存在于同一表的另一列中的值? [复制]

在 SQL 中,我可以在另一列中获取与它们没有关联的特定值的列中的值吗?