sql >> Base de Datos >  >> RDS >> Oracle

Identificador no válido en consulta anidada doble con ORDER BY y ROWNUM

En la subconsulta escalar que está utilizando, solo puede hacer referencia a las tablas de la consulta "principal" "un nivel anidado hacia abajo", no más abajo, como ha visto. (Creo que esta restricción se elimina en la versión 12, ¿así que tal vez pueda actualizar su base de datos?;-)

En la subconsulta escalar, está intentando obtener el valor de la columna INSERTDATE de la primera fila de acuerdo con su pedido. Eso también se puede escribir sin anidar de la siguiente manera:

SELECT
O.INSERTDATE OrderCreateDate,

-- Determine delivery date
(SELECT MAX(DD.INSERTDATE) KEEP (
          DENSE_RANK FIRST ORDER BY
          DD.CLOSED ASC, ABS(TRUNC(CURRENT_DATE-TO_DATE(TO_CHAR(DD.INSERTDATE, 'DDMMYYYY'), 'DDMMYYYY'))) ASC
        )
   FROM MY_DELIVERYDATE_TABLE DD
   JOIN MY_ORDERPOS_TABLE OP2 ON DD.FK_ORDERPOS=OP2.ID
   LEFT OUTER JOIN MY_ORDER_TABLE O2 ON OP2.FK_ORDER=O2.ID
   WHERE OP2.FK_ORDER=O.ID AND -- This will no longer give "Invalid identifier O.ID"
         DD.DELFLAG IS NULL AND OP2.DELFLAG IS NULL
) DeliveryDate

FROM MY_ORDER_TABLE O
WHERE O.ID = 620; -- ID goes here!

MANTENER (DENSE_RANK FIRST le dice a la función MAX, que debe calcular el MAX solo de esas filas que se clasifican primero en la cláusula ORDER BY. Entonces, si su PEDIDO POR es "único", MAX se aplicará solo a uno fila. Si su PEDIDO POR no es "único" y puede tener duplicados, puede pensar si desea el MÁXIMO o el MÍNIMO (o agregar algo al PEDIDO POR para que sea único).

(Si hubiera estado en la versión 12 de Oracle, una alternativa al truco KEEP (DENSE_RANK) sería usar la cláusula FIRST 1 ROW ONLY de la declaración SELECT.)