SQL 之列转行Unpivot函数

这是总结SQL知识点的第二篇文章,一次只总结一个知识点,尽量说明白。上次我们谈到行转列,用的是Pivot函数,这次我们来谈谈Unpivot函数。(这里是用的数据库是SQLSERVER,与其他数据库是类似的,大家放心看就好)

先看一个小问题

Customer
在这张图中,表示的是顾客用不同手机号给Phone1、Phone2、Phone3拨打电话的情况,但是机灵的你,想变个花样来看看,比如下面这样的。
Unpivot
大家想想看如何实现呢?想下,2分钟后再看哟

先创建数据
CREATE TABLE dbo.CustomerPhones
(
  CustomerID INT PRIMARY KEY, -- FK
  Phone1 VARCHAR(32),
  Phone2 VARCHAR(32),
  Phone3 VARCHAR(32)
);
INSERT dbo.CustomerPhones
  (CustomerID, Phone1, Phone2, Phone3)
VALUES
  (1,'705-491-1111', '705-491-1110', NULL),
  (2,'613-492-2222', NULL, NULL),
  (3,'416-493-3333', '416-493-3330', '416-493-3339');

  select * from dbo.CustomerPhones

查看数据如下:

Data

Upivot 实现行转列
	select * from dbo.CustomerPhones   -----数据源
	unpivot 
(	
	 Phone FOR Phones IN (Phone1, Phone2, Phone3)
            ##Phone1、Phone2、Phone3这些列的结果转为行上的结果,成为一列,
      ##并且有了新的列名为Phone
) up

结果如下:
Result

参考文献:
1.Use SQL Server’s UNPIVOT operator to help normalize output
2.SQL之行转列Pivot用法

<think>嗯,用户问的是UNPIVOT函数怎么把多数值转行。首先,我得回想一下UNPIVOT的基本概念。UNPIVOTSQL中是用来将转换为行的操作,和PIVOT相反。用户可能遇到了需要把多个的数据转换成行的情况,比如处理宽表变长表的问题。 接下来,我应该考虑UNPIVOT的具体语法结构。通常,UNPIVOT需要指定要转换的,以及生成的新名,比如值和标识。例如,在SQL Server中,语法大概是SELECT ... FROM ... UNPIVOT (value_column FOR name_column IN (1, 2, ...))这样。可能用户需要知道如何同时处理多个数值,所以得举一个具体的例子说明。 然后,用户的需求可能涉及到实际应用场景。比如,销售数据原来按月分,现在需要把每个月的数据转成行,这样更容易进行时间序分析或者汇总。这时候用UNPIVOT就能把多个月份的转换成行,每行包含月份和对应的销售额。 需要注意的常见问题可能包括数据类型一致,因为UNPIVOT要求所有被转换的数据类型相同。如果有不同的数据类型,可能需要先转换类型。另外,名处理可能需要使用引号或者方括号,特别是当名有特殊字符或空格的时候。 用户可能还想知道不同数据库的支持情况,比如SQL Server、Oracle、PostgreSQL等是否都支持UNPIVOT。有些数据库可能没有直接的UNPIVOT函数,需要用其他方法比如UNION ALL来实现。这时候可能需要简要说明替代方案,但主要聚焦在UNPIVOT本身。 最后,要确保回答结构清晰,分步骤或者分点说明,可能先讲语法,再举例,然后注意事项。这样用户能够一步步理解如何使用UNPIVOT处理多转换。还要检查是否用了正确的中文术语,避免技术术语翻译错误。</think>### UNPIVOT函数详解:多数值转行 #### 1. **核心作用** UNPIVOTSQL中用于将**多数值转换为行**的操作,常用于将“宽表”转换为“长表”(即存储转为行存储)。 **适用场景**:数据包含相同语义的数值(如各月销售额、不同指标值等),需合并为便于分析的结构。 --- #### 2. **基本语法(以SQL Server为例)** ```sql SELECT 标识, 值名, 转行后的值 FROM 原表 UNPIVOT ( 值名 FOR 名占位符 IN (1, 2, 3) ) AS 别名; ``` --- #### 3. **具体案例** **原表数据**(存储季度销售额): | 产品ID | Q1销售额 | Q2销售额 | Q3销售额 | |--------|----------|----------|----------| | 1001 | 500 | 600 | 700 | **目标**:将季度转为行,输出: | 产品ID | 季度 | 销售额 | |--------|--------|--------| | 1001 | Q1销售额 | 500 | | 1001 | Q2销售额 | 600 | | 1001 | Q3销售额 | 700 | **SQL实现**: ```sql SELECT 产品ID, 季度, 销售额 FROM 原表 UNPIVOT ( 销售额 FOR 季度 IN (Q1销售额, Q2销售额, Q3销售额) ) AS unpvt; ``` --- #### 4. **关键注意事项** - **数据类型一致性**:所有被转换的必须为**相同数据类型**(例如均为数值型)。 - **名处理**:若名含特殊字符或空格,需用方括号包裹(如`[2023 Sales]`)。 - **兼容性**:不同数据库语法可能不同(如Oracle需用`UNPIVOT INCLUDE NULLS`处理空值)。 --- #### 5. **替代方案(无UNPIVOT时)** 若数据库不支持UNPIVOT,可用`UNION ALL`模拟: ```sql SELECT 产品ID, 'Q1销售额' AS 季度, Q1销售额 AS 销售额 FROM 原表 UNION ALL SELECT 产品ID, 'Q2销售额', Q2销售额 FROM 原表 UNION ALL SELECT 产品ID, 'Q3销售额', Q3销售额 FROM 原表; ``` --- #### 6. **典型应用场景** - 时间序分析(如月度数据转行) - 多指标合并(如将“温度”“湿度”转为统一的行存储) - 数据清洗(减少冗余,适配BI工具输入格式)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值