如何在不使用 SQL 中的 PIVOT 函数的情况下进行透视?

Posted

技术标签:

【中文标题】如何在不使用 SQL 中的 PIVOT 函数的情况下进行透视?【英文标题】:How to pivot without using PIVOT functions in SQL? 【发布时间】:2021-05-15 17:26:42 【问题描述】:

我想在不使用任何 PIVOT 函数但仅使用纯 SQL 的情况下对表进行透视(例如 PostgreSQL 语法)。

以这个数据集为例:

Order |   Element | Value |
---------------------------
1     | Item      | Bread |
1     | Quantity  |  3    |
1     | TotalCost |  3,30 |
2     | Item      | Pizza |
2     | Quantity  |  2    |
2     | TotalCost |  10   |
3     | Item      | Pasta |
3     | Quantity  |  5    |
3     | TotalCost |  2,50 |

我希望以Order 列为中心,并有类似的内容:

Order | Item | Quantity | TotalCost |
-------------------------------------
1     | Bread |    3    |    3,30   |
2     | Pizza |    2    |    10     |
3     | Pasta |    5    |    2,50   |

如果不使用任何数据透视函数,我将如何再次实现这一点?

【问题讨论】:

【参考方案1】:

解决方案 A

使用CASE WHEN 语句:

SELECT Order, 
       MAX(CASE WHEN Element = 'Item' THEN Value END) AS Item, 
       MAX(CASE WHEN Element = 'Quantity' THEN Value END) AS Quantity, 
       MAX(CASE WHEN Element = 'TotalCost' THEN Value END) AS TotalCost
FROM MyTable
GROUP BY 1

解决方案 B

使用自左连接:

SELECT A.Order, A.Item, B.Quantity, C.TotalCost
FROM
    (SELECT Order, Value as Item
    FROM MyTable
    WHERE Element = 'Item') as A
    LEFT JOIN
    (SELECT Order, Value as Quantity
    FROM MyTable
    WHERE Element = 'Quantity') as B ON A.Order = B.Order
    LEFT JOIN
    (SELECT Order, Value as TotalCost
    FROM MyTable
    WHERE Element = 'TotalCost') as C ON B.Order = C.Order

后者可能没有那么高效,但有些用例可能会派上用场。

【讨论】:

【参考方案2】:

在 Postgres 中,您将使用 FILTER:

SELECT Order, 
       MAX(Value) FILTER (WHERE Element = 'Item') AS Item, 
       MAX(Value) FILTER (WHERE Element = 'Quantity') AS Quantity, 
       MAX(Value) FILTER (WHERE Element = 'TotalCost') AS TotalCost
FROM MyTable
GROUP BY 1;

请注意,ORDER 是一个 SQL 关键字,因此它不适合作为列名。

【讨论】:

以上是关于如何在不使用 SQL 中的 PIVOT 函数的情况下进行透视?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用数据透视和反透视的情况下在 SQL Server 中水平显示数据?

如何在sql中使用pivot到多列

如何在不使用 Group By / 有函数的情况下过滤 SQL 中的数据

如何在不使用临时表或视图的情况下在多个列上使用 PIVOT [重复]

如何在不使用 to_date /to_char 函数的情况下比较 oracle sql 中的日期?

Oracle SQL Developer:如何使用 PIVOT 函数将行转置为列