2016-10-18 2 views
0

Я пытаюсь объединить несколько подзапросов, чтобы избежать попаданий в массивный стол (42B строк) несколько раз и получитьМульти СЛУЧАЯ Колонка КОГДА в Teradata

«[3771] Незаконное выражение в том, когда раздел CASE. "

,SUM(CASE 
    WHEN (oh.LOCN_NBR,oh.WK_NBR) IN (SELECT LOCN_NBR,START_WK FROM VT_STORES) 
    THEN oh.TTL_UN_QT 
    ELSE NULL 
    END) AS BEGINNING_OH 

Есть ли способ сделать несколько столбцов в операторах в сазе, или я застрял положить их в соединении/где в подзапросе, как это в настоящее время?

Edit: Полный запрос по запросу:

SELECT 
      oh.LOCN_NBR AS LOCN_NBR 
      ,item.ITEM_ID AS ITEM_ID 
      ,SUM(CASE 
       WHEN oh.WK_NBR = (SELECT WK_NBR FROM ALEX_ARP_VIEWS_PRD.REF_CUSTOM_TIME WHERE cust_time_id=2) 
       THEN oh.TTL_UN_QT 
       ELSE NULL 
      END) AS SALEABLE_QTY 
      ,SUM(CASE 
       WHEN oh.WK_NBR = (SELECT LY_WK_NBR FROM ALEX_ARP_VIEWS_PRD.REF_CUSTOM_TIME WHERE cust_time_id=2) 
       THEN oh.TTL_UN_QT 
       ELSE NULL 
      END) AS SALEABLE_QTY_LY 
      ,SUM(CASE 
       WHEN (oh.LOCN_NBR,oh.WK_NBR) IN (SELECT LOCN_NBR,PRI_START_WK FROM VT_STORES) 
       THEN oh.TTL_UN_QT 
       ELSE NULL 
      END) AS BEGINNING_OH_LY 
      ,SUM(CASE 
       WHEN (oh.LOCN_NBR,oh.WK_NBR) IN (SELECT LOCN_NBR,START_WK FROM VT_STORES) 
       THEN oh.TTL_UN_QT 
       ELSE NULL 
      END) AS BEGINNING_OH 

FROM 
      ALEX_ARP_VIEWS_PRD.FACT_WKLY_OPR_INS oh 
      INNER JOIN VT_STORES stores ON oh.LOCN_NBR = stores.LOCN_NBR 
      INNER JOIN VT_ITEM item ON oh.VEND_PACK_ID = item.VEND_PACK_ID 
WHERE    
      INS_TYP_CD='H' 
      AND TTL_UN_QT <> 0 
      AND WK_NBR >= (SELECT MIN(PRI_START_WK) FROM VT_STORES) 
GROUP BY 
    oh.LOCN_NBR 
    ,item.ITEM_ID 
+0

В чем ключ 'VT_STORES'? – dnoeth

+0

locn_nbr является ключом VT_STORES –

+0

Нужно ли логике запроса читать все строки 42B, или вы ожидаете, что какое-то из условий, где будет ограничивать число значимо? Если да, то из плана вы видите, что это ограничение работает? Как любопытство, это большая таблица, состоящая только из 5-6 полей, которые мы видим или у нее много дополнительных столбцов? И вам нужно сделать всю логику в одном запросе, или вы можете использовать некоторые шаги во временных/летучих таблицах? – Insac

ответ

0

Вам не нужно использовать IN. Вы можете использовать exists:

SUM(CASE WHEN EXISTS (SELECT 1 FROM VT_STORES v WHERE oh.LOCN_NBR = v.LOCN_NBR AND oh.WK_NBR = v.START_WK) 
     THEN oh.TTL_UN_QT 
    END) AS BEGINNING_OH 

Однако, я не 100% уверен, что проблема заключается в IN. Многие базы данных не разрешают подзапросы в качестве аргументов для функций агрегации. Я не уверен, поддерживает ли Teradata эту функциональность.

+0

Я добавил полный запрос в соответствии с запросом (в его нерабочем состоянии). Если я комментирую функции третьего и четвертого случаев, запрос работает, поэтому подзапросы разрешены ... он просто выглядит как часть с несколькими столбцами, которая не работает. –

0

Я пытаюсь объединить несколько подзапросов, чтобы избежать столкновения с массивным столом несколько раз

Multi-колонки подзапросы разрешены только в WHERE, но не в CASE. Перезапись на EXISTS, вероятно, не улучшит производительность, план может быть более сложным.

Вы просто попытайтесь скрыть сложность, но это все-таки внешнее соединение в фоновом режиме, как это:

,Sum(CASE WHEN stores.LOCN_NBR IS NOT NULL THEN oh.TTL_UN_QT END) AS BEGINNING_OH 
... 
FROM oh LEFT JOIN 
(
    SELECT LOCN_NBR,START_WK FROM VT_STORES 
) AS stores 
ON stores.LOCN_NBR = oh.LOCN_NBR 
AND stores.START_WK = oh.WK_NBR 

Вы можете показать свой текущий запрос (по крайней мере, те части, вы пытаетесь оптимизировать)?

Edit:

Когда VT_STORES.locn_nbr уникален, это должно возвращать тот же результат:

SELECT 
      oh.LOCN_NBR AS LOCN_NBR 
      ,item.ITEM_ID AS ITEM_ID 
      ,Sum(CASE 
       WHEN oh.WK_NBR = (SELECT Min(WK_NBR) FROM ALEX_ARP_VIEWS_PRD.REF_CUSTOM_TIME WHERE cust_time_id=2) 
       THEN oh.TTL_UN_QT 
       ELSE NULL 
      END) AS SALEABLE_QTY 
      ,Sum(CASE 
       WHEN oh.WK_NBR = (SELECT Min(LY_WK_NBR) FROM ALEX_ARP_VIEWS_PRD.REF_CUSTOM_TIME WHERE cust_time_id=2) 
       THEN oh.TTL_UN_QT 
       ELSE NULL 
      END) AS SALEABLE_QTY_LY 
      ,Sum(CASE 
       WHEN oh.WK_NBR= stores.PRI_START_WK 
       THEN oh.TTL_UN_QT 
      END) AS BEGINNING_OH_LY 
      ,Sum(CASE 
       WHEN oh.WK_NBR = stores.START_WK 
       THEN oh.TTL_UN_QT 
      END) AS BEGINNING_OH 

FROM 
      ALEX_ARP_VIEWS_PRD.FACT_WKLY_OPR_INS oh 
      INNER JOIN VT_STORES stores ON oh.LOCN_NBR = stores.LOCN_NBR 
      INNER JOIN VT_ITEM item ON oh.VEND_PACK_ID = item.VEND_PACK_ID 
WHERE    
      INS_TYP_CD='H' 
      AND TTL_UN_QT <> 0 
      AND WK_NBR >= (SELECT Min(PRI_START_WK) FROM VT_STORES) 
GROUP BY 
    oh.LOCN_NBR 
    ,item.ITEM_ID 

Другие скалярные подзапросы должны быть хорошо, потому что они возвращают только одну строку и оптимизатор знает это.

+0

Я добавил полный запрос в соответствии с запросом (в его нерабочем состоянии). Если я комментирую функции третьего и четвертого случаев, запрос работает, поэтому подзапросы разрешены ... он просто выглядит как часть с несколькими столбцами, которая не работает. –

+0

Это работает, но, к сожалению, это приводит к тому, что я ударяю ограничения пространства. Я думаю, что я решил объединить то, что раньше было 4-мя запросами (каждая операция SUM), до двух запросов - первые две, а затем вторая. Спасибо за вашу помощь. Я был слишком обеспокоен проблемой с заявлением. –

+0

Вы должны проверить Объясните, есть ли что-то плохое в этом. Скалярные подзапросы должны отображаться как шаг получения ответов или основываться на инкрементальном Plannig. Возможно, вам придется поговорить с вашим администратором базы данных, чтобы увеличить катушку ... – dnoeth

0

Re: Есть ли способ сделать несколько столбцов в операторах в сазе

нет.

Re: , чтобы избежать удара массивного стола (42B строк) несколько раз

, который один большой? Я не вижу, как, если бы работала составная статья IN, вы бы избегали многократного попадания в большую таблицу по сравнению с использованием столбцов соединения/добавления в предложении where.

вы пытались что-то вроде:

SELECT 
    ... 
     ,SUM(CASE 
      WHEN SELECT COUNT(*) FROM VT_STORES 
       WHERE LOCN_NBR = oh.LOCN_NBR AND 
       PRI_START_WK = oh.WK_NBR > 1 
       THEN oh.TTL_UN_QT 
      END) AS BEGINNING_OH_LY 
     ,SUM(CASE 
      WHEN SELECT COUNT(*) FROM VT_STORES 
        WHERE LOCN_NBR = oh.LOCN_NBR AND 
        START_WK = oh.WK_NBR > 1 
        THEN oh.TTL_UN_QT 
      END) AS BEGINNING_OH 
     FROM 
      ... 

?

Если это VT_STORES, что это большое, попробуйте:

ALEX_ARP_VIEWS_PRD.FACT_WKLY_OPR_INS oh INNER JOIN 
(select 
    LOCN_NBR, 
    PRI_START_WK, 
    START_WK 
from 
    VT_STORES) stores ON 
oh.LOCN_NBR = stores.LOCN_NBR and 
(PRI_START_WK = oh.WK_NBR OR 
START_WK = oh.WK_NBR) 

хотя я видел производительность хитов от использования OR положений в соединениях, вы могли бы быть лучше с двумя внутренними соединениями, один на каждой неделю вы хотите.

+0

Извините, я должен был уточнить в своем вопросе - большая таблица - таблица ALEX_ARP_VIEWS_PRD.FACT_WKLY_OPR_INS. Первоначальный дизайн имел каждую операцию SUM как отдельный отдельный запрос. –

Смежные вопросы