LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

利用SQL内置函数实现数据表行列转换:PIVOT和UPIVOT函数

admin
2024年2月5日 13:39 本文热度 561

数据库自带的行转列函数有哪些呢?这里要介绍PIVOT 和 UNPIVOT 函数了。这两个函数为我们提供了便捷的方式来实现数据表的行列转换。PIVOT 用于旋转数据,将行转为列,UNPIVOT 是其逆操作,将列转为行。

下面是一些示例:

PIVOT 示例:

SELECT * FROM ( SELECT year, month, qty FROM Sales)PIVOT (SUM(qty) FOR month IN ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

在这个例子中,我们将“月份”列中的每个月份转换为了各自的列,并将每个月的销售量总和填充到相应的列中。

UNPIVOT 示例:

SELECT * FROM ( SELECT year, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec FROM Sales) UNPIVOT (qty FOR month IN (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec))

在这个例子中,我们将每个月的列转换为了一个“月份”列,并将相应的销售量总和填充到新的“qty”列中。

目前,Oracle和SQL Server数据库系统都支持 PIVOT 和 UNPIVOT 函数。MySQL和PostgreSQL并不直接支持,但可以通过其他SQL语句实现类似的效果(如上篇文章介绍的方法)。

那如果要转为列的行,它的内容和个数不确定,该怎么办?比如上面示例中的月份不是固定的12个月。

我首先想到的是利用SQL的子查询,比如:

SELECT ...FROM ...PIVOT (SUM(value) FOR column IN (SELECT DISTINCT column FROM ...))


但以上查询在SQL Server中是无效的,这是因为SQL Server和Oracle在编译查询时需要知道所有的列名,而子查询返回的结果直到运行时才知道。

解决此问题的一种常见方法是使用动态SQL,即使用SQL编写并执行SQL语句。这样,你可以先运行一个查询来获取所有唯一的列或行名,然后将这些名字拼接到你的PIVOT或UNPIVOT查询中,最后执行这个查询。

假设我们有一个名为sales的表,其中包含以下数据:

Product   | Year | Sale
--------------------------
ProductA  | 2019 | 100
ProductA  | 2020 | 150
ProductB  | 2019 | 200
ProductB  | 2020 | 220
ProductC  | 2019 | 300
ProductC  | 2020 | 350


我们希望按产品进行行列转换,得到以下结果:

Year | ProductA | ProductB | ProductC
--------------------------------------
2019 | 100      | 200      | 300
2020 | 150      | 220      | 350


如果产品的类别是固定的,我们可以使用静态SQL来实现。例如,在SQL Server中,我们可以使用PIVOT操作符:

SELECT Year, [ProductA], [ProductB], [ProductC] FROM (SELECT Product, Year, Sale FROM sales) AS SourceTable PIVOT (SUM(Sale) FOR Product IN ([ProductA], [ProductB], [ProductC])) AS PivotTable;

但是,如果产品的类别是动态的,我们需要使用动态SQL。在SQL Server中,我们可以使用以下方法:

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);SET @columns = STUFF((  SELECT ',' + QUOTENAME(Product)  FROM sales  GROUP BY Product  ORDER BY Product  FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
SET @sql = N'SELECT Year, ' + @columns + 'FROM (  SELECT Product, Year, Sale  FROM sales) AS SourceTablePIVOT (  SUM(Sale)  FOR Product IN (' + @columns + ')) AS PivotTable;';
EXEC sp_executesql @sql;

这个例子首先构造了一个包含所有产品的列名的字符串(@columns),然后使用这个字符串来构造PIVOT查询的SQL语句(@sql),最后执行这个SQL语句。


该文章在 2024/2/6 18:47:06 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved