L'utilizzo di un alias in una clausola WHERE
Domanda
Ho una domanda che è destinata a mostrarmi tutte le righe della tabella A, che non sono stati aggiornati abbastanza recente. (Ogni riga deve essere aggiornata entro 2 mesi dopo "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
L'ultima riga nella clausola WHERE causa un errore "ORA-00904 non valido Identifier". Inutile dire che non voglio ripetere l'intera funzione DECODE nella mia clausola WHERE. qualche idea? (Entrambe le correzioni e soluzioni alternative accettate ...)
Soluzione
Ciò non è possibile direttamente, perché cronologicamente, DOVE accade prima SELECT, che è sempre l'ultimo passaggio della catena di esecuzione.
Si può fare un sub-selezionare e filtrare su di esso:
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 po 'di informazioni salito dai commenti:
Non ci dovrebbero essere calo di prestazioni. Oracle non ha bisogno di materializzare query interno prima di applicare esterno Condizioni - Oracle prenderà in considerazione trasformando questa query internamente spingere il predicato giù nella interno interrogare e lo farà se si tratta di costo efficace. - Justin Cave
Altri suggerimenti
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
Oppure si può avere il tuo alias in una clausola HAVING
Proprio come un approccio alternativo a voi può fare:
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
Inoltre è possibile creare una vista permanente per la coda e selezionare dalla vista.
CREATE OR REPLACE VIEW_1 AS (SELECT ...);
SELECT * FROM VIEW_1;
E 'possibile definire in modo efficace una variabile che può essere utilizzato sia nella SELECT, WHERE e altre clausole.
Una subquery non necessariamente consentire appropriato legame alle colonne della tabella di riferimento, tuttavia ESTERNO APPLICARE fa.
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
Complimenti a Syed Mehroz Alam .