使用超过 255 个 UNION ALL 语句修复 SQL

Posted

技术标签:

【中文标题】使用超过 255 个 UNION ALL 语句修复 SQL【英文标题】:Fix SQL with more than 255 UNION ALL statements 【发布时间】:2019-05-21 20:26:49 【问题描述】:

有什么方法可以优化 DB2 中的以下 SQL:

下面的 SQL 是 257 个 UNION ALL 语句的组合。此查询在我组合少于 255 个 UNION ALL 语句时有效,但在我们尝试执行超过 255 个 UNION ALL 语句时失败并出现以下错误。

错误:

THE STATEMENT IS TOO LONG OR TOO COMPLEX. SQLCODE=-101, SQLSTATE=54001, DRIVER=3.63.75 SQL Code: -101, SQL State: 54001

DB2 SQL 查询:

SELECT
   '400005' as COLUMN1,
   'DB' as COLUMN2,
   '1' AS COLUMN3
FROM sysibm.sysdummy1

UNION ALL

SELECT
   '400005' as COLUMN1,
   'DB' as COLUMN2,
    '2' AS COLUMN3
FROM sysibm.sysdummy1

UNION ALL

.
.
.
.

UNION ALL
SELECT
   '400005' as COLUMN1,
   'DB' as COLUMN2,
    '257' AS COLUMN3
FROM sysibm.sysdummy1

我遇到了几个链接https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/codes/src/tpc/n129.html,但它们并没有多大用处。

任何输入都会有所帮助。

谢谢!

【问题讨论】:

请在 SQL 编辑器中运行相同的语句(超过 255 个 UNION ALL 语句),您应该可以看到错误。 找到一个有 257 行的表从中选择,从中获取 row_number() 并限制为 257。交叉连接到 SELECT '400005' as COLUMN1, 'DB' as COLUMN2 from sysibm.sysdummy1) 你到底想做什么?您应该不需要 255 Union All 语句附近的任何地方。我们能否获得更多有关您的表的上下文以及查询应该做什么? 【参考方案1】:

考虑递归 CTE:

WITH data (COLUMN1, COLUMN2, COLUMN3) AS    
    (SELECT '400005' as COLUMN1,
            'DB' as COLUMN2,
            1 AS COLUMN3
     FROM sysibm.sysdummy1

     UNION ALL

     SELECT '400005' as COLUMN1,
            'DB' as COLUMN2,
            COLUMN3 + 1 AS COLUMN3
     FROM data
     WHERE data.COLUMN3 < 255)

SELECT COLUMN1, COLUMN2, CAST(COLUMN3 AS VARCHAR(5)) AS COLUMN3 FROM data;

DB2 demo (dbfiddle.uk)

【讨论】:

是的,这也有效!并感谢 db2 fiddle 链接。此外,这也不会因为必须有一个包含 257 条记录的表而受到影响。 @xQbert 超过 257 条记录的表不是问题...如果没有其他问题,只需使用 syscolumns。虽然一个真正的numbers 表对很多事情都很有用.. @charles 这里没有参数。系统不必生成数字,性能会提高,您可以用它做很多事情。我的观点很简单,一个人必须拥有该表,因此它依赖于这样的表,并且取决于最终可能成为问题的所需记录的数量。而这个解决方案没有这样的限制。尽管;允许的递归可能有上限...【参考方案2】:

我们在这里处理的是关系数据库。连接(交叉连接)到具有所需 257 行的表并使用它的 row_number()。 1:M 关系为我们提供了所需的 257 行,我们仅限制为 257 行,以获得您的工会试图实现的相同结果。

SYSIBM.SYSTABLES 可能有超过 257 行...所以我将使用它作为示例。

奇怪的是,这可能是少数几个没有 order by 的限制 (Fetch) 之一。

SELECT '400005' as COLUMN1, 'DB' as COLUMN2,  Z.RN as COLUMN3
FROM sysibm.sysdummy1
CROSS JOIN (SELECT ROW_NUMBER() OVER () as RN 
            FROM SYSIBM.SYSTABLES  --assuming over 257 rows
            FETCH FIRST 257 ROWS ONLY) Z

虽然不确定 DB2 是否支持交叉连接语法(可能取决于版本)...所以可能会使用较旧的连接语法...

SELECT '400005' as COLUMN1, 'DB' as COLUMN2,  Z.RN as COLUMN3
FROM sysibm.sysdummy1,
     (SELECT ROW_NUMBER() OVER () as RN 
      FROM SYSIBM.SYSTABLES  --assuming over 257 rows
      FETCH FIRST 257 ROWS ONLY) Z

【讨论】:

【参考方案3】:

Db2 的平台和版本很重要...在 IBM i v7.2 和更高版本的 Db2 上肯定支持以下内容...并且可能在用于 LUW 的 DB2 上...不确定 Db2 for Z/操作系统。

我怀疑如果 XQbert 的答案还不够,表值构造函数可能就是答案..

作为公用表表达式 (CTE) 使用 with

with tbl(column1, column2, column3) as (
  values ('400005', 'DB', '1')
        , ('400005', 'DB', '2')  
        ...
        , ('400005', 'DB', '257')
)
select * from tbl;

或作为嵌套表表达式 (NTE)

select * 
from table(('400005', 'DB', '1')
            , ('400005', 'DB', '2')  
            ...
            , ('400005', 'DB', '257')
) tbl(column1, column2, column3);

【讨论】:

我喜欢。给这只猫剥皮的方法很多。 ;P 我只是不想输入所有这些数字:P

以上是关于使用超过 255 个 UNION ALL 语句修复 SQL的主要内容,如果未能解决你的问题,请参考以下文章

oracle union 和 union all

SQL语句:使用了union all后怎么分组排序

具有三个或更多选择的 UNION ALL 的正确语句

使用 Union All 优化 SQL 查询

SQL语句中:UNION与UNION ALL的区别

SQL语句中:UNION与UNION ALL的区别