2016-07-29 107 views
2

下面您將找到三個示例表和數據以及查詢。這個例子可能看起來很有意思,但它是更大的(近1500行)SQL查詢的一部分。原始查詢很好,但我在添加一些新功能時遇到了問題。嵌套WITH子查詢中的Oracle SQL無效標識符錯誤

CREATE TABLE rule_table (
    id_rule_table NUMBER (10), 
    name VARCHAR2 (24), 
    goal NUMBER (10), 
    amount NUMBER (10) 
); 

INSERT INTO rule_table (id_rule_table, name, goal, amount) VALUES(1, 'lorem', 2, 3); 
INSERT INTO rule_table (id_rule_table, name, goal, amount) VALUES(2, 'ipsum', 3, 3); 
INSERT INTO rule_table (id_rule_table, name, goal, amount) VALUES(3, 'dolor', 4, 3); 

CREATE TABLE content_table (
    id_content_table NUMBER (10), 
    name VARCHAR2 (24), 
    show_flag NUMBER (10) 
); 

INSERT INTO content_table (id_content_table, name, show_flag) VALUES(1, 'lorem', 0); 
INSERT INTO content_table (id_content_table, name, show_flag) VALUES(2, 'ipsum', 1); 
INSERT INTO content_table (id_content_table, name, show_flag) VALUES(3, 'dolor', 1); 

CREATE TABLE module_table (
    id_module_table NUMBER (10), 
    id_content_table NUMBER (10), 
    name VARCHAR2 (24), 
    amount NUMBER (10) 
); 

INSERT INTO module_table (id_module_table, id_content_table, name, amount) VALUES(1, 2, 'lorem', 10); 
INSERT INTO module_table (id_module_table, id_content_table, name, amount) VALUES(2, 2, 'ipsum', 11); 
INSERT INTO module_table (id_module_table, id_content_table, name, amount) VALUES(3, 2, 'dolor', 12); 

SELECT RULE.id_rule_table 
FROM rule_table RULE 
WHERE (
    CASE 
    WHEN RULE.goal <= (

      WITH contentTbl (id_content_table) 
      AS (
       SELECT id_content_table 
       FROM content_table 
       WHERE show_flag = 1 
      ), 

      modulesTbl (id_content_table, id_module_table) 
      AS (
       SELECT C.id_content_table, M.id_module_table 
       FROM contentTbl C 
       JOIN module_table M ON M.id_content_table = C.id_content_table 
       WHERE 4 < M.amount - RULE.amount 
      ) 

      SELECT SUM(M.id_module_table) 
      FROM contentTbl C 
      JOIN modulesTbl M ON C.id_content_table = M.id_content_table 
    ) 
    THEN 1 
    ELSE 0 
    END 
) = 1; 

DROP TABLE rule_table; 
DROP TABLE content_table; 
DROP TABLE module_table; 

如果你試試這個,你將收到錯誤ORA-00904: 「治」, 「金額」:無效的標識符。問題在於「WHERE 4 < M.amount - RULE.amount」。

如果在該行中用某個數字替換RULE.amount(例如,Where WHERE 4 < M.amount - 3),那麼查詢將運行得很好。

如上所述,這是一個來自更大查詢的片段測試用例,所以查詢結構不能(或者希望不需要)被改變太多。也就是說,理想情況下,我正在尋找一種解決方案,該解決方案將允許我在子查詢中使用RULE.amount,而不更改「WHEN RULE.goal < =()」塊內部的其他任何內容。

我想在Oracle 11g上運行這個。

最後一件事,我試着搜索谷歌和stackoverflow的解決方案,但我找不出正確的術語來描述我的問題。最接近的東西似乎是嵌套的相關子查詢,但似乎並不完全正確。

回答

0

考慮到這是一個非常大的查詢中的一部分,這裏有使這項工作所需的手術變化:

  1. 移動WHERE 4 < M.amount - RULE.amount條件了CTE並進入主查詢,以便RULE在範圍內。

  2. 修改modulesTbl CTE返回附加列amount,以便M.amount現在可用於主查詢。

有了這些變化2,查詢應該是這樣的:

SELECT RULE.id_rule_table 
FROM rule_table RULE 
WHERE (
    CASE 
    WHEN RULE.goal <= (

      WITH contentTbl (id_content_table) 
      AS (
       SELECT id_content_table 
       FROM content_table 
       WHERE show_flag = 1 
      ), 

      modulesTbl (id_content_table, id_module_table, amount) -- add amount 
      AS (
       SELECT C.id_content_table, M.id_module_table, M.amount -- add amount 
       FROM contentTbl C 
       JOIN module_table M ON M.id_content_table = C.id_content_table 
      ) 

      SELECT SUM(M.id_module_table) 
      FROM contentTbl C 
      JOIN modulesTbl M ON C.id_content_table = M.id_content_table 
           AND 4 < M.amount - RULE.amount -- moved from CTE to here 
    ) 
    THEN 1 
    ELSE 0 
    END 
) = 1; 
+1

...併爲OP的利益,原因書面不起作用查詢是該規則是可見的第一級子查詢(SELECT SUM(...)FROM ...)但對第二級子查詢不可見(SELECT C.id_content_table .....)Oracle不會關聯多個嵌套的子查詢級別較深。 – mathguy