Verwendung eines Alias in WHERE-Klausel
Frage
Ich habe eine Abfrage, die ist gemeint, um zu zeigen, mir alle Zeilen in Tabelle A, die nicht aktualisiert wurden vor kurzem genug.(Jede Zeile sollte aktualisiert werden innerhalb von 2 Monaten nach "month_no".):
SELECT A.identifier
, A.name
, TO_NUMBER(DECODE( A.month_no
, 1, 200803
, 2, 200804
, 3, 200805
, 4, 200806
, 5, 200807
, 6, 200808
, 7, 200809
, 8, 200810
, 9, 200811
, 10, 200812
, 11, 200701
, 12, 200702
, NULL)) as MONTH_NO
, TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE
FROM table_a A
, table_b B
WHERE A.identifier = B.identifier
AND MONTH_NO > UPD_DATE
Die Letzte Zeile in der WHERE-Klausel bewirkt, dass ein "ORA-00904 Ungültiger Bezeichner" error.Unnötig zu sagen, ich will nicht, wiederholen Sie den gesamten DECODE-Funktion in meiner WHERE-Klausel.Irgendwelche Gedanken?(Beide fixes und workarounds akzeptiert...)
Lösung
Dies ist direkt nicht möglich, da in chronologischer Reihenfolge, WHERE geschieht vor SELECT, der immer der letzte Schritt in der Ausführung Kette ist.
Sie können eine Unterauswahl tun und Filter auf sie:
SELECT * FROM
(
SELECT A.identifier
, A.name
, TO_NUMBER(DECODE( A.month_no
, 1, 200803
, 2, 200804
, 3, 200805
, 4, 200806
, 5, 200807
, 6, 200808
, 7, 200809
, 8, 200810
, 9, 200811
, 10, 200812
, 11, 200701
, 12, 200702
, NULL)) as MONTH_NO
, TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE
FROM table_a A
, table_b B
WHERE A.identifier = B.identifier
) AS inner_table
WHERE
MONTH_NO > UPD_DATE
Interessante paar Informationen aus den Kommentaren nach oben verschoben:
Es sollte keine Leistungseinbußen sein. Oracle muss nicht materialisieren Innen Abfragen vor dem Anwenden äußeren Bedingungen - Oracle wird prüfen Transformieren dieser Abfrage intern und schiebt das Prädikat nach unten in die Innen abfragen und wird dies tun, wenn es kostet Wirksam. - Justin Cave
Andere Tipps
SELECT A.identifier
, A.name
, TO_NUMBER(DECODE( A.month_no
, 1, 200803
, 2, 200804
, 3, 200805
, 4, 200806
, 5, 200807
, 6, 200808
, 7, 200809
, 8, 200810
, 9, 200811
, 10, 200812
, 11, 200701
, 12, 200702
, NULL)) as MONTH_NO
, TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE
FROM table_a A, table_b B
WHERE .identifier = B.identifier
HAVING MONTH_NO > UPD_DATE
Oder Sie können Ihren alias in einem HAVING
Klausel
So wie ein alternativer Ansatz für Sie tun kann:
WITH inner_table AS
(SELECT A.identifier
, A.name
, TO_NUMBER(DECODE( A.month_no
, 1, 200803
, 2, 200804
, 3, 200805
, 4, 200806
, 5, 200807
, 6, 200808
, 7, 200809
, 8, 200810
, 9, 200811
, 10, 200812
, 11, 200701
, 12, 200702
, NULL)) as MONTH_NO
, TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE
FROM table_a A
, table_b B
WHERE A.identifier = B.identifier)
SELECT * FROM inner_table
WHERE MONTH_NO > UPD_DATE
Sie können auch eine permanente Ansicht für Ihre Warteschlange erstellen und aus Sicht auswählen.
CREATE OR REPLACE VIEW_1 AS (SELECT ...);
SELECT * FROM VIEW_1;
Es ist möglich, effektiv eine Variable zu definieren, die sowohl in der SELECT, WHERE und anderen Klauseln verwendet werden können.
Eine Unterabfrage nicht unbedingt für geeignete erlaubt Bindung an die referenzierten Tabellenspalten jedoch OUTER Gegenstandslos.
SELECT A.identifier
, A.name
, vars.MONTH_NO
, TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE
FROM table_a A
, table_b B ON A.identifier = B.identifier
OUTER APPLY (
SELECT
-- variables
MONTH_NO = TO_NUMBER(DECODE( A.month_no
, 1, 200803
, 2, 200804
, 3, 200805
, 4, 200806
, 5, 200807
, 6, 200808
, 7, 200809
, 8, 200810
, 9, 200811
, 10, 200812
, 11, 200701
, 12, 200702
, NULL))
) vars
WHERE vars.MONTH_NO > UPD_DATE
Ein großes Lob an Syed Mehroz Alam .