sql - oci_execute - Usar un alias en una cláusula WHERE
oci_execute() ora 00904 invalid identifier (5)
Tengo una consulta que debe mostrarme las filas de la tabla A que no se han actualizado lo suficiente. (Cada fila debe actualizarse dentro de los 2 meses posteriores a "mes_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 Identificador no válido". Huelga decir que no quiero repetir toda la función DECODE en mi cláusula WHERE. ¿Alguna idea? (Ambas correcciones y soluciones temporales aceptadas ...)
Es posible definir efectivamente una variable que se puede usar tanto en las cláusulas SELECT, WHERE como en otras.
Una subconsulta no necesariamente permite un enlace apropiado a las columnas de tabla referenciadas, sin embargo, lo hace OUTER APPLY.
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 Mehroz Alam .
Esto no es posible directamente, porque cronológicamente, WHERE sucede antes de SELECT, que siempre es el último paso en la cadena de ejecución.
Puede hacer una selección secundaria y filtrar en ella:
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
Un poco de información interesante pasó de los comentarios a:
No debería haber ningún golpe de rendimiento. Oracle no necesita materializar consultas internas antes de aplicar condiciones externas: Oracle considerará transformar esta consulta internamente y empujará el predicado hacia abajo en la consulta interna y lo hará si es rentable. - Justin Cave
O puede tener su alias en una cláusula HAVING
Tal como lo puede hacer un enfoque alternativo para usted:
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 puede crear una vista permanente para su cola y seleccionar desde la vista.
CREATE OR REPLACE VIEW_1 AS (SELECT ...);
SELECT * FROM VIEW_1;
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