2016-07-29 6 views
2

Im Folgenden finden Sie drei Beispieltabellen und Daten zusammen mit einer Abfrage. Dieses Beispiel scheint künstlich zu sein, aber es ist Teil einer viel größeren (fast 1500 Zeilen) SQL-Abfrage. Die ursprüngliche Abfrage funktioniert einwandfrei, aber ich habe ein Problem beim Hinzufügen neuer Funktionen festgestellt.Oracle SQL ungültiger Bezeichner Fehler in geschachtelte MIT Unterabfrage

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; 

Wenn Sie dies versuchen Sie den Fehler ORA-00904 erhalten: "RULE" "AMOUNT". Ungültige Kennung. Das Problem liegt in der Zeile "WHERE 4 < M.amount - RULE.amount".

Wenn Sie RULE.amount in dieser Zeile mit einer Nummer (z. B. WHERE 4 < M.amount - 3) ersetzen, wird die Abfrage problemlos ausgeführt.

Wie oben erwähnt, handelt es sich um einen Snippet-Testfall aus einer viel größeren Abfrage, so dass die Struktur der Abfrage nicht (oder hoffentlich nicht notwendigerweise) zu sehr geändert werden muss. Das heißt, im Idealfall suche ich nach einer Lösung, die es mir ermöglicht, RULE.amount in der Unterabfrage zu verwenden, ohne etwas anderes zu ändern, als die SQL innerhalb des "WHEN RULE.goal < =()" -Blocks.

Ich versuche, dies auf Oracle 11g ausführen.

Eine letzte Sache, ich versuchte, google und stackoverflow nach Lösungen zu suchen, aber ich konnte die korrekte Terminologie nicht herausfinden, um mein Problem zu beschreiben. Die nächste Sache schien eine verschachtelte korrelierte Unterabfrage zu sein, aber das scheint nicht genau zu stimmen.

Antwort

0

Unter Berücksichtigung, dass dies nur einen Teil einer viel größeren Abfrage, hier sind die chirurgischen Änderungen erforderlich, um diese Arbeit zu machen:

  1. Bewegen Sie den WHERE 4 < M.amount - RULE.amount Zustand des CTE aus und in die Haupt Abfrage, so dass RULE im Anwendungsbereich ist.

  2. Ändern Sie den modulesTbl CTE eine zusätzliche Spalte zurück amount so dass M.amount an der Hauptabfrage ist jetzt verfügbar.

Mit diesen zwei Änderungen würde die Abfrage wie folgt aussehen:

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

... und zum Nutzen der OP, der Grund, warum die Abfrage wie geschrieben nicht funktioniert ist, dass RULE ist sichtbar die Unterabfrage der ersten Ebene (SELECT SUM (...) FROM ...), aber sie ist NICHT für die Unterabfrage der zweiten Ebene sichtbar (SELECT C.id_content_table .....) Oracle korreliert keine Unterabfragen, die mehr als eins verschachtelt sind Ebene tief. – mathguy

Verwandte Themen