Teradata中的多列案例

时间:2016-10-18 21:26:49

标签: sql teradata

我试图合并一些子查询以避免多次敲击一个大表(42B行)并获得

  

" [3771] CASE表达式的WHEN子句中的非法表达。"

Integer[] intValues =  new Integer [] {1,2,3,4,5};      
Integer[] outputValues = Arrays.stream(intValues).map(i ->    (i*2)).toArray(Integer[] :: new);
Arrays.stream(outputValues).forEach(x -> System.out.println(x));

有没有办法在CASE语句中执行多列IN语句,或者我是不是将它们放在子查询中的join / where中,因为它是当前的?

编辑:按要求进行完整查询:

,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

3 个答案:

答案 0 :(得分: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是否允许此功能。

答案 1 :(得分:0)

  

我正在尝试整合一些子查询以避免多次访问大量表

多列子查询仅在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

您能否显示当前查询(至少是您尝试优化的那些部分)?

修改

当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

其他Scalar子查询应该没问题,因为它们只返回一行而优化器知道这一点。

答案 2 :(得分:0)

re:有没有办法在CASE语句中做多列IN语句

没有

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子句的性能命中率,但是你可能会更好地使用两个内连接,每周一个你想要的。