有什么方法可以优化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,但是它们没有多大用处。
任何输入都会有所帮助。
谢谢!
答案 0 :(得分:2)
考虑递归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;
答案 1 :(得分:1)
我们在这里处理关系数据库。联接(交叉联接)到具有所需257行的表,并使用它的row_number()。 1:M关系为我们提供了所需的257行,而我们仅限制为257行才能获得您的工会试图达到的相同结果。
SYSIBM.SYSTABLES
可能有超过257行...所以我将使用它作为示例。
奇怪的是,这可能是没有顺序的限制(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
答案 2 :(得分:1)
重要的是要提及Db2的平台和版本...以下内容在IBM i v7.2及更高版本的Db2上肯定受支持...并且可能在LUW的DB2上得到支持...不确定Z / Db2的版本操作系统。
我怀疑XQbert的答案是否足够,表值构造函数可能就是答案。
作为使用with
的公用表表达式(CTE)
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);