---
title: "UNPIVOT 子句 - OceanBase 数据库 V5.0.1 | OceanBase 文档中心"
description: UNPIVOT 子句 描述 UNPIVOT 子句用于将查询结果中的列转换为行，即列转行，是 PIVOT 的逆操作。它把多个列的值合并到同一个列中，同时新增一列来标识原值来自哪一列。 例如，使用 PIVOT 已经把各部门的工资汇总值展开为多个列，使用 UNPIVOT 可以把这些列重新合并为“部门 + 工资”的行记录。 …
image: https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*OSPzQ6GUQF4AAAAAQHAAAAgAeiGDAQ/original
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 5.0.1

# UNPIVOT 子句

更新时间：2026-10-27 18:07:22

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V5.0.1/zh-CN/700.reference/500.sql-reference/100.sql-syntax/300.common-tenant-of-oracle-mode/900.sql-statement-of-oracle-mode/200.dml-of-oracle-mode/500.select-of-oracle-mode/700.unpivot-clause-of-oracle-mode.md)  

## 描述

`UNPIVOT` 子句用于将查询结果中的列转换为行，即列转行，是 `PIVOT` 的逆操作。它把多个列的值合并到同一个列中，同时新增一列来标识原值来自哪一列。

例如，使用 `PIVOT` 已经把各部门的工资汇总值展开为多个列，使用 `UNPIVOT` 可以把这些列重新合并为“部门 + 工资”的行记录。

#### 说明

`UNPIVOT` 子句仅适用于 Oracle 模式。

## 权限要求

执行 `UNPIVOT` 查询时，需要当前用户对参与转换的表或视图拥有 `SELECT` 权限。有关 OceanBase 数据库权限的详细介绍，参见 [Oracle 模式下的权限分类](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000006619034)。

## 语法

```sql
unpivot_clause:
    UNPIVOT [ { INCLUDE | EXCLUDE } NULLS ]
    ( { column | ( column [, column... ]) }
    pivot_for_clause
    unpivot_in_clause
    )

pivot_for_clause:
    FOR { column | ( column [, column... ]) }

unpivot_in_clause:
    IN
    ( { column | ( column [, column... ]) } [ AS { literal | ( literal [, literal... ]) } ]
        [, { column | ( column [, column... ]) } [ AS { literal | ( literal [, literal... ]) } ]]
    )

```

## 参数解释

| 参数 | 说明 |
| --- | --- |
| `INCLUDE NULLS` | 可选项，转换后值为 `NULL` 的行也作为结果行输出。 |
| `EXCLUDE NULLS` | 可选项，转换后值为 `NULL` 的行不作为结果行输出。 |
| `column` | 转换后接收数据的列，即值列。 |
| `pivot_for_clause` | 指定新增的标识列，用于存放 `IN` 子句中定义的标签值。 |
| `unpivot_in_clause` | 指定要转换为行的列。`AS` 后面指定该列在标识列中对应的标签值；不指定 `AS` 时使用列名作为标签值。 |

`UNPIVOT` 的输出列由三部分组成：未参与转换的列、`pivot_for_clause` 指定的标识列、`unpivot_in_clause` 中指定的值列。

#### 注意

不指定 `INCLUDE NULLS` 或 `EXCLUDE NULLS` 时，OceanBase 数据库按 `EXCLUDE NULLS` 处理，即值为 `NULL` 的行不会输出。该默认行为与 Oracle 数据库（默认 `INCLUDE NULLS`）不同，如需保留 `NULL` 行，请显式指定 `INCLUDE NULLS`。

## 使用限制

- `unpivot_in_clause` 中的列需要能够转换为同一种数据类型，否则会报错 `ORA-01790: expression must have same datatype as corresponding expression`。
 - `AS` 后面只支持常量表达式，不支持使用列或子查询动态生成标签值。
 - 暂不支持 `UNPIVOT` 作为 joined table 的别名。
 - 暂不支持 `UNPIVOT` 操作的目标表是 natural join 的情况。
 - `UNPIVOT` 之后可以继续使用 `WHERE`、`ORDER BY` 等子句，此时这些子句作用于转换后的结果集。

## 示例

先创建示例表 `emp` 并插入数据。

```sql
obclient> CREATE TABLE emp (
    empno NUMBER(4),
    job VARCHAR2(9),
    deptno NUMBER(2),
    sal NUMBER(7,2)
);

```

```sql
obclient> INSERT INTO emp VALUES
    (7369, 'CLERK', 20, 800),
    (7499, 'SALESMAN', 30, 1600),
    (7521, 'SALESMAN', 30, 1250),
    (7566, 'MANAGER', 20, 2975),
    (7654, 'SALESMAN', 30, 1250),
    (7698, 'MANAGER', 30, 2850),
    (7782, 'MANAGER', 10, 2450),
    (7788, 'ANALYST', 20, 3000),
    (7839, 'PRESIDENT', 10, 5000),
    (7844, 'SALESMAN', 30, 1500),
    (7876, 'CLERK', 20, 1100),
    (7900, 'CLERK', 30, 950),
    (7902, 'ANALYST', 20, 3000),
    (7934, 'CLERK', 10, 1300);

```

### 示例 1：将多个列转换为行

先使用 `PIVOT` 把各部门的工资汇总值展开为列，并保存为视图。

```sql
obclient> CREATE VIEW emp_pivot AS
    SELECT *
    FROM (SELECT job, deptno, sal FROM emp)
    PIVOT (
        SUM(sal)
        FOR deptno IN (10 AS dept_10, 20 AS dept_20, 30 AS dept_30, 40 AS dept_40)
    );

```

```sql
obclient> SELECT * FROM emp_pivot;

```

查询结果如下：

```sql
+-----------+---------+---------+---------+---------+
| JOB       | DEPT_10 | DEPT_20 | DEPT_30 | DEPT_40 |
+-----------+---------+---------+---------+---------+
| CLERK     |    1300 |    1900 |     950 |    NULL |
| SALESMAN  |    NULL |    NULL |    5600 |    NULL |
| MANAGER   |    2450 |    2975 |    2850 |    NULL |
| ANALYST   |    NULL |    6000 |    NULL |    NULL |
| PRESIDENT |    5000 |    NULL |    NULL |    NULL |
+-----------+---------+---------+---------+---------+
5 rows in set

```

再使用 `UNPIVOT` 把 `DEPT_10`、`DEPT_20`、`DEPT_30`、`DEPT_40` 四列转换回行，并用 `AS` 指定标识列的取值。

```sql
obclient> SELECT *
    FROM emp_pivot
    UNPIVOT (
        sal
        FOR deptno IN (dept_10 AS 10, dept_20 AS 20, dept_30 AS 30, dept_40 AS 40)
    )
    ORDER BY deptno, job;

```

查询结果如下：

```sql
+-----------+--------+------+
| JOB       | DEPTNO | SAL  |
+-----------+--------+------+
| CLERK     |     10 | 1300 |
| MANAGER   |     10 | 2450 |
| PRESIDENT |     10 | 5000 |
| ANALYST   |     20 | 6000 |
| CLERK     |     20 | 1900 |
| MANAGER   |     20 | 2975 |
| CLERK     |     30 |  950 |
| MANAGER   |     30 | 2850 |
| SALESMAN  |     30 | 5600 |
+-----------+--------+------+
9 rows in set

```

`DEPT_40` 列的值全部为 `NULL`，按默认的 `EXCLUDE NULLS` 行为，`SAL` 为 `NULL` 的行（包括 `DEPT_40` 列对应的 5 行）不会出现在结果中，因此结果只有 9 行。如果希望保留这些行，在 `UNPIVOT` 后显式指定 `INCLUDE NULLS` 即可，此时结果行数由 9 行增加到 20 行。

### 示例 2：不指定标签值

不指定 `AS` 时，标识列的取值为原列名。

```sql
obclient> SELECT *
    FROM (
        SELECT 1 AS id, 'Laptop' AS product, 100 AS q1, 150 AS q2 FROM dual
    )
    UNPIVOT (
        amount FOR quarter IN (q1, q2)
    );

```

查询结果如下：

```sql
+------+---------+--------+---------+
| ID   | PRODUCT | QUARTER | AMOUNT |
+------+---------+--------+---------+
|    1 | Laptop  | Q1      |    100 |
|    1 | Laptop  | Q2      |    150 |
+------+---------+--------+---------+
2 rows in set

```

## 相关文档

- [PIVOT 子句](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000007152176)
 - [SELECT](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000006621606)

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
