Oracle 视图 - 求和到变量

Oracle view - sum to variable

如何缩短以下 select 语句?

create or replace view V_AMV_PLG_QUOTES_50_MS as 
select 
    sum(NVL(ASK_SIZE,0))    as ASK_VOLUME, 

CASE WHEN 
          sum(CASE WHEN NVL(ASK_SIZE,0)=0 THEN CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END ELSE ASK_SIZE END)=0 THEN 1 
     ELSE sum(CASE WHEN NVL(ASK_SIZE,0)=0 THEN CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END ELSE ASK_SIZE END) END     as ASK_PRICE,


    EXCHANGE_SK         as EXCHANGE_SK, 
    PRODUCT_SK          as PRODUCT_SK, 
    BUSINESS_DATE       as BUSINESS_DATE 
from 
    S_AMV_PLG_QUOTE_AGG quotes 
where NVL(BASE_CURR_ASK_PRICE ,0) > 0
group by 
    EXCHANGE_SK, 
    PRODUCT_SK, 
    BUSINESS_DATE 

请注意,很长的计算出现了两次。我能以某种方式将它插入到变量中吗?并且只在变量上使用 CASE 运算符? (注意我们那里有求和函数..)

您不能在视图中创建和使用变量。如果你只是想避免重复嵌套的 case 语句,你可以将它(和 NVL)移动到一个内联视图中:

select 
    sum(MY_ASK_SIZE)    as ASK_VOLUME, 
    CASE WHEN sum(MY_ASK_PRICE)=0 THEN 1 
        ELSE sum(MY_ASK_PRICE)
        END             as ASK_PRICE,
    EXCHANGE_SK         as EXCHANGE_SK, 
    PRODUCT_SK          as PRODUCT_SK, 
    BUSINESS_DATE       as BUSINESS_DATE 
from (
    select
        EXCHANGE_SK, PRODUCT_SK, BUSINESS_DATE,
        NVL(ASK_SIZE,0) as MY_ASK_SIZE,
        CASE WHEN NVL(ASK_SIZE,0)=0 THEN
                CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END
            ELSE ASK_SIZE
            END AS MY_ASK_PRICE
    from  S_AMV_PLG_QUOTE_AGG quotes 
    where NVL(BASE_CURR_ASK_PRICE ,0) > 0
)
group by 
    EXCHANGE_SK, 
    PRODUCT_SK, 
    BUSINESS_DATE;

NVL和case都执行一次,别名分别为MY_ASK_SIZE和MY_ASK_PRICE;然后在外部查询中使用这些别名,包括总和。

如果您也想避免重复 SUM,请将其连同 group-by 子句一起移至内嵌视图中:

select 
    ASK_VOLUME          as ASK_VOLUME, 
    CASE WHEN ASK_PRICE=0 THEN 1
        ELSE ASK_PRICE
        END             as ASK_PRICE,
    EXCHANGE_SK         as EXCHANGE_SK, 
    PRODUCT_SK          as PRODUCT_SK, 
    BUSINESS_DATE       as BUSINESS_DATE 
from (
    select
        EXCHANGE_SK, PRODUCT_SK, BUSINESS_DATE,
        SUM(NVL(ASK_SIZE,0)) as ASK_VOLUME,
        SUM(CASE WHEN NVL(ASK_SIZE,0)=0 THEN
                CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END
            ELSE ASK_SIZE
            END) AS ASK_PRICE
    from  S_AMV_PLG_QUOTE_AGG quotes 
    where NVL(BASE_CURR_ASK_PRICE ,0) > 0
    group by 
        EXCHANGE_SK, 
        PRODUCT_SK, 
        BUSINESS_DATE
);

你的大部分列别名都是多余的,但我坚持使用你的模式。

虽然这主要是装饰性的; Oracle 的优化器可能足够聪明,无论如何只执行一次实际计算,所以我不希望看到太多(或任何)性能差异。

我创建了一个简单的 ifZeroReturnOne 函数:

CREATE OR REPLACE FUNCTION ifZeroReturnOne (expr IN NUMBER)
RETURN NUMBER
IS retval NUMBER;
BEGIN
SELECT CASE WHEN expr=0 THEN 1
ELSE expr END
INTO retval
FROM DUAL;
RETURN (retval);
END;

比我在查询中使用的:

select sum(NVL(ASK_SIZE,0))    as ASK_VOLUME, 

ifZeroReturnOne (sum(CASE WHEN NVL(ASK_SIZE,0)=0 THEN CASE WHEN BASE_CURR_ASK_PRICE=0 THEN 0 ELSE 1 END ELSE ASK_SIZE END)    as ASK_PRICE,


EXCHANGE_SK         as EXCHANGE_SK, 
etc...............

如果有更好的建议请告诉我