仅使用 case 语句将列转置为行并联接所有表

Transposing Columns to Rows Using only Case Statement and Joining All Tables

提问人:Living Madara 提问时间:11/7/2023 最后编辑:Adrian MaxwellLiving Madara 更新时间:11/7/2023 访问量:69

问:

我有一个查询,它生成了数百万行,有 10 列。我已经发布了原始查询的图片,它是我正在使用的简化版本,名为“详细信息”。

我需要将“Description”列中的每个行/值转置为分隔列,并将列:CountValueAmountAAmountB 转置为 3 个单独的表,每个表都有自己的列来自“Description”列。最后,我需要将它们全部合并到一个表中。

这是原始表详细信息

Table Details

我已将“Description”中的每个值转置到它们自己的列中,并将“CountValue”移置到一列下,并用它填充每一行。这是表计数

Table Counts

在这里,我为 AmountA 做了同样的事情。这是表 AmtA

AmtA

对表 AmtB 进行了相同的转置:

AmtB

最后在 Table AmountCount 中将它们连接在一起,这需要是我的最终输出:

AmountCount

需要注意的几点:

  • 我只能使用 case 语句和聚合函数。我不能使用枢轴函数或其他更复杂的函数。
  • 上面的表格只是我实际想要处理的一个示例,它有数百万行和大量列。
  • 我希望所有转置表和生成的表的顺序与原始表的顺序相同。

我尝试从表 Counts 中转置 CountValue 和 Description 列的查询如下:

with Counts as
    (
        select distinct
        t1.CountsA,
        t1.CountsB,
        t1.CountsC
        t1.CountsD,
        ('CountValue') as ColCountE,
        sum(case when Description = 'Arizona' then t1.CountValue end) as ColArizona,
        sum(case when Description = 'California ' then t1.CountValue end) as ColCalifornia,
        sum(case when Description = 'Florida' then t1.CountValue end) as ColFlorida,
        sum(case when Description = 'Iowa' then t1.CountValue end) as ColIowa,
        sum(case when Description = 'Kansas ' then t1.CountValue end) as ColKansas,
        sum(case when Description = 'Kentucky' then t1.CountValue end) as ColKentucky

        from Details t1
        group by t1.CountsA,
        t1.CountsB,
        t1.CountsC
        t1.CountsD,
        CountValue
    )
SELECT * from Counts

我尝试了各种分组组合,包括上述组合,但我没有得到所需的结果。如果有人能提供正确的代码,我们将不胜感激。这是我需要的主要代码,任何使用 case 语句进行转置的建议。

我的另一个问题是关于合并所有转置表。假设每个表中都存在的列 CountsA 和 CountsB 是键。在最后一个表中,如果我将所有必需的列都保留在 select 中,然后在表 Counts、AmtA 和 AmtB 中内部连接 CountsA 和 CountsB,是否可以?

sql snowflake-cloud-data-platform 案例 转置 RDBMS

评论

1赞 Jorge Campos 11/7/2023
请阅读此内容并进行相应的编辑: 提出一个好的结构化查询语言 (SQL) 问题的提示
2赞 June7 11/7/2023
为使用的 RDBMS 添加标签。为什么不使用图像 meta.stackoverflow.com/questions/285551/...
1赞 June7 11/7/2023
“没有得到所需的结果”是什么意思 - 错误消息,错误的结果,什么也没发生?为什么需要使用子查询?不要将 DISTINCT 与 GROUP BY 混用。
1赞 June7 11/7/2023
标记“rdbms”未指定您正在使用的 RDBMS。这是MySQL,SQLServer还是什么?此外,您想要的数据操作是“透视”。
1赞 Adrian Maxwell 11/7/2023
在网站帮助中,请勿发布代码、数据、错误消息等图像 - 将文本复制或键入到问题中。请保留使用图像来制作图表或演示渲染错误,这些错误无法通过文本准确描述。有关更多信息,请参阅 Meta FAQ 条目:为什么在提问时不上传代码/错误的图像?

答:

0赞 Adrian Maxwell 11/7/2023 #1

运行 3 个不同的查询然后联接这些结果效率不高,只需不断添加更多大小写表达式以涵盖所有金额列即可。因此,您不需要(或类似)在 select 子句中,因为所有数值列都可以在一个查询中得到满足,并且列名暗示数据源。(您可能需要重新访问列的命名,以便更清楚地说明这一点。('CountValue') as ColCountE

SELECT
      t1.CountsA
    , t1.CountsB
    , t1.CountsC
    , t1.CountsD
    /* CountValue */
    , sum(CASE WHEN Description = 'Arizona' THEN t1.CountValue END) AS ColArizona
    , sum(CASE WHEN Description = 'California ' THEN t1.CountValue END) AS ColCalifornia
    , sum(CASE WHEN Description = 'Florida' THEN t1.CountValue END) AS ColFlorida
    , sum(CASE WHEN Description = 'Iowa' THEN t1.CountValue END) AS ColIowa
    , sum(CASE WHEN Description = 'Kansas ' THEN t1.CountValue END) AS ColKansas
    , sum(CASE WHEN Description = 'Kentucky' THEN t1.CountValue END) AS ColKentucky
    /* AmountA */
    , sum(CASE WHEN Description = 'Arizona' THEN t1.AmountA END) AS Arizona_A
    , sum(CASE WHEN Description = 'California ' THEN t1.AmountA END) AS California_A
    , sum(CASE WHEN Description = 'Florida' THEN t1.AmountA END) AS Florida_A
    , sum(CASE WHEN Description = 'Iowa' THEN t1.AmountA END) AS Iowa_A
    , sum(CASE WHEN Description = 'Kansas ' THEN t1.AmountA END) AS Kansas_A
    , sum(CASE WHEN Description = 'Kentucky' THEN t1.AmountA END) AS Kentucky_A
    /* AmountB */
    , sum(CASE WHEN Description = 'Arizona' THEN t1.AmountB END) AS Arizona_B
    , sum(CASE WHEN Description = 'California ' THEN t1.AmountB END) AS California_B
    , sum(CASE WHEN Description = 'Florida' THEN t1.AmountB END) AS Florida_B
    , sum(CASE WHEN Description = 'Iowa' THEN t1.AmountB END) AS Iowa_B
    , sum(CASE WHEN Description = 'Kansas ' THEN t1.AmountB END) AS Kansas_B
    , sum(CASE WHEN Description = 'Kentucky' THEN t1.AmountB END) AS Kentucky_B
FROM Details t1
GROUP BY
      t1.CountsA
    , t1.CountsB
    , t1.CountsC
    , t1.CountsD

笔记

  • 在聚合函数中使用大小写表达式称为“条件聚合”
  • 该子句将从您在该子句中指定的列中形成唯一的行,还会测试是否所有行都是唯一定义的 - 因此,如果已经使用 ,则它是多余的。group byselect distinctgroup by
  • 不要包含需要聚合到子句中的列,包含的列有时称为“非聚合”列group by
  • 您问题的 SQL 中缺少 2 个逗号,这是我更喜欢上面看到的布局的原因。在 PoorSQL 上尝试一下,例如在选项中查找“尾随逗号”