Исправьте SQL с более чем 255 операторами UNION ALL - PullRequest
0 голосов
/ 21 мая 2019

Можно ли как-нибудь оптимизировать приведенный ниже SQL в DB2:

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

Запрос SQL DB2:

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, но они не очень полезны.

Любые входные данные будут полезны.

Спасибо!

Ответы [ 3 ]

2 голосов
/ 22 мая 2019

Рассмотрим рекурсивный 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 (dbfiddle.uk)

1 голос
/ 22 мая 2019

Платформа и версия Db2 важны для упоминания ... ниже гарантированно поддерживается ниже на Db2 для IBM i v7.2 и выше ... и, вероятно, на DB2 для LUW ... не уверен насчет Db2 для Z /OS.

Я подозреваю, что если ответа 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);
1 голос
/ 22 мая 2019

Мы имеем дело с реляционной базой данных здесь. Соедините (Cross join) таблицу с 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
...