El uso de un Alias en una cláusula WHERE
Pregunta
Tengo una consulta que está destinado a mostrarme ninguna fila de la tabla A que no se han actualizado recientemente suficiente. (Cada fila debe actualizarse dentro de 2 meses después de "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
La última línea en la cláusula WHERE provoca un error "ORA-00904 no válida de identificación". No hace falta decir que no quiero repetir toda la función DECODE en mi cláusula WHERE. ¿Alguna idea? (Ambas correcciones y soluciones aceptadas ...)
Solución
Esto no es posible directamente, porque cronológicamente, donde sucede antes SELECT, que siempre es el último paso en la cadena de ejecución.
Puede hacer un sub-select y filtrar en él:
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
poco interesante de la información llega desde la presentación de observaciones:
No debe haber ningún impacto en el rendimiento. Oracle no tiene que materializarse consultas internas antes de aplicar el exterior condiciones - Oracle tendrá en cuenta la transformación de esta consulta interna y empujar el predicado hacia abajo en el interior consultar y lo hará si es costo eficaz. - Justin cueva
Otros consejos
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
O usted puede tener su alias en una cláusula HAVING
Al igual que un enfoque alternativo al que puede hacer:
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
También se puede crear una vista permanente de la cola y seleccione la vista.
CREATE OR REPLACE VIEW_1 AS (SELECT ...);
SELECT * FROM VIEW_1;
Es posible definir de manera efectiva una variable que se puede utilizar tanto en el SELECT, WHERE y otras cláusulas.
Una subconsulta no necesariamente permite apropiado de unión a las columnas de tabla referenciada, sin embargo OUTER APPLY hace.
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
Felicitaciones a Syed Alam Mehroz .