带有 IN CLAUSE 动态值的 SQL Pivot

Posted

技术标签:

【中文标题】带有 IN CLAUSE 动态值的 SQL Pivot【英文标题】:SQL Pivot with dynamic values for IN CLAUSE 【发布时间】:2020-09-18 15:12:52 【问题描述】:

我有一个格式如下的表格

详情

+-------------------+--------+------------+----------------+-------+
| LOB               | Level  | Year_Month | Classification | Count |
+-------------------+--------+------------+----------------+-------+
| Mergers& Acqu     | Level3 | 2020-05    | Statement      | 356   |
+-------------------+--------+------------+----------------+-------+
| Wealth Management | Level2 | 2020-05    | Lending        | 23    |
+-------------------+--------+------------+----------------+-------+
| Finance           | Level3 | 2020-06    | Statement      | 65    |
+-------------------+--------+------------+----------------+-------+

如何旋转具有计数的 Year_month 列?

预期结果

+-------------------+--------+----------------+---------+---------+
| LOB               | Level  | Classification | 2020-05 | 2020-06 |
+-------------------+--------+----------------+---------+---------+
| Mergers& Acqu     | Level3 | Statement      | 356     | 0       |
+-------------------+--------+----------------+---------+---------+
| Wealth Management | Level2 | Lending        | 23      | 0       |
+-------------------+--------+----------------+---------+---------+
| Finance           | Level3 | Statement      | 0       | 65      |
+-------------------+--------+----------------+---------+---------+

我尝试了以下查询,但没有得到想要的结果

SELECT * FROM DETAILS
PIVOT (SUM(Count) FOR YEAR_MONTH IN (SELECT distinct YEAR_MONTH FROM DETAILS))

如何使 IN CLAUSE 具有动态值而不是预设值?

【问题讨论】:

可以使用动态SQL:asktom.oracle.com/pls/asktom/… 【参考方案1】:

使用替换变量的选项:

SQL> set verify off
SQL> clear columns
columns cleared
SQL> column llist new_value slist
SQL> select listagg(ym, ', ') within group (order by ym) as llist
  2  from (select distinct
  3          chr(39) || year_month ||chr(39) || ' as "' || year_month ||'"' ym
  4        from details
  5      );

LLIST
--------------------------------------------------------------------------------
'2020-05' as "2020-05", '2020-06' as "2020-06"

SQL> select * from
  2  (select lob, clevel, classification, year_month, ccount from details)
  3     pivot (sum(ccount)
  4            for year_month in (&slist));

LOB               CLEVEL CLASSIFIC    2020-05    2020-06
----------------- ------ --------- ---------- ----------
Finance           level3 statement                    65
Wealth Management level2 lending           23
Mergers and Acqu  level3 statement        356

SQL>

它的缺点是,如果LISTAGG 的结果超过 4000 个字符,它将失败(但是,再一次,你将如何处理包含超过 500 个月的结果? )。

【讨论】:

【参考方案2】:

Oracle 不支持PIVOT 函数的IN 子句中的动态值,除非您使用PIVOT XML。运行查询时,Oracle 需要它始终具有相同的列数。

如果您要使用PIVOT XML,以下是您的查询示例

WITH
    details (lob_val,
             level_val,
             year_month,
             classification,
             COUNT)
    AS
        (SELECT 'Mergers& Acqu', 'Level3', '2020-05', 'Statement', 356 FROM DUAL
         UNION ALL
         SELECT 'Wealth Management', 'Level2', '2020-05', 'Lending  ', 23 FROM DUAL
         UNION ALL
         SELECT 'Finance', 'Level3', '2020-06', 'Statement', 65 FROM DUAL)
SELECT *
  FROM (SELECT lob_val, level_val, year_month, classification, COUNT FROM details)
       PIVOT XML (SUM (COUNT) AS sum_count
                 FOR (year_month)
                 IN (SELECT DISTINCT year_month
                       FROM details));

【讨论】:

以上是关于带有 IN CLAUSE 动态值的 SQL Pivot的主要内容,如果未能解决你的问题,请参考以下文章

执行SQL时出现: ORDER BY clause is not in GROUP BY clause and contains nonaggregated c

What does a (+) sign mean in an Oracle SQL WHERE clause?

MySQL [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause

MySQLjava.sql.SQLException:Unknown column ‘****‘ in ‘where clause‘错误问题原因以及如何解决?

MySQLjava.sql.SQLException:Unknown column ‘****‘ in ‘where clause‘错误问题原因以及如何解决?

Oracle中实现find_in_set