2017-03-28 122 views
0

在Oracle 12(和APEX)中,我遇到了WHERE子句中的CASE語句問題。該場景是主表,ORDER和PRODUCTS_BOUGHT表,因此這是一對多關係。我有一個報告,在PRODUCTS_BOUGHT上有一個過濾器。過濾器填充名爲P36_PRODUCT_LISTING的綁定變量/ APEX頁面項。如果用戶選擇給定產品,我希望報告只顯示那些包含給定產品的訂單。該過濾器包含單詞'All',不應該做任何過濾,以及我們攜帶的每件產品。Oracle:在Where子句中使用Case語句

我的SQL語句是

Select distinct 
    :P36_PRODUCT_LISTING,  
    LISTAGG(product_name, ', ') WITHIN GROUP (ORDER BY product_name) OVER (PARTITION BY B.SALES_ORDER_NUMBER) AS products, 
    ... 
from ORDER A, PRODUCTS_BOUGHT B 
where 
A.SALES_ORDER_NUMBER = B.SALES_ORDER_NUMBER 
and 
case when 
:P36_PRODUCT_LISTING = 'All' then 1 = 1 
else a.SALES_ORDER_NUMBER IN (SELECT SALES_ORDER_NUMBER from PRODUCTS_BOUGHT where PRODUCT_NAME = :P36_PRODUCT_LISTING) end 

當我運行的聲明,我得到的錯誤是缺少關鍵字。 我在做什麼錯?

+0

使用AND OR的/不是這樣的! – jarlh

回答

1

請勿使用case。只需使用布爾邏輯:

where (:P36_PRODUCT_LISTING = 'All' or 
     a.SALES_ORDER_NUMBER IN (SELECT SALES_ORDER_NUMBER 
           from PRODUCTS_BOUGHT 
           where PRODUCT_NAME = :P36_PRODUCT_LISTING 
           ) 
    ) 

case的問題(如你寫它)是Oracle不從邏輯表達式作爲有效值治療價值。有些數據庫可以,但不是Oracle。

另外:

  • 不要from子句中使用逗號。始終使用正確,明確的join語法。
  • 使用表名稱縮寫表的別名。閱讀查詢和修復錯誤更容易。
  • select distinct在這裏不應該是必要的。你正在做一個沒有group by的聚合,所以只有一行。

所以:

Select :P36_PRODUCT_LISTING,  
     LISTAGG(b.product_name, ', ') WITHIN GROUP (ORDER BY b.product_name) OVER (PARTITION BY B.SALES_ORDER_NUMBER) AS products, 
    ... 
from ORDER o join 
    PRODUCTS_BOUGHT B 
    on p.SALES_ORDER_NUMBER = B.SALES_ORDER_NUMBER 
    where (:P36_PRODUCT_LISTING = 'All' or 
      o.SALES_ORDER_NUMBER IN (SELECT SALES_ORDER_NUMBER 
            from PRODUCTS_BOUGHT 
            where PRODUCT_NAME = :P36_PRODUCT_LISTING 
            ) 
     ); 
+0

我真的開始懷疑,究竟是誰在教舊的連接語法呢?這已經過去了將近10年了 – JohnHC

+0

不是誰在教老語法的問題,這是一個問題,我學習了20年前的語法...;) – user1009073

0

案例被設計爲返回一個值,而不是一個聲明..

一次或代替

where :P36_PRODUCT_LISTING = 'All' 
or (:P36_PRODUCT_LISTING <> 'All' 
    and a.SALES_ORDER_NUMBER IN (SELECT SALES_ORDER_NUMBER from PRODUCTS_BOUGHT where PRODUCT_NAME = :P36_PRODUCT_LISTING))