Oracle
 sql >> Base de données >  >> RDS >> Oracle

Identifiant non valide dans une requête à double imbrication avec ORDER BY et ROWNUM

Dans la sous-requête scalaire que vous utilisez, vous ne pouvez référencer les tables qu'à partir de la requête "principale" "un niveau imbriqué vers le bas", pas plus bas, comme vous l'avez vu. (Je crois que cette restriction est levée dans la version 12, alors peut-être pouvez-vous simplement mettre à jour votre base de données ?;-)

Dans la sous-requête scalaire, vous essayez d'obtenir la valeur de la colonne INSERTDATE de la première ligne en fonction de votre commande. Cela peut aussi s'écrire sans imbrication comme suit :

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!

KEEP (DENSE_RANK FIRST indique à la fonction MAX qu'elle doit calculer le MAX uniquement de ces lignes qui se classent premières dans la clause ORDER BY. Donc, si votre ORDER BY est "unique", MAX ne sera appliqué qu'à un ligne. Si votre ORDER BY n'est pas "unique" et peut avoir des doublons, vous pouvez vous demander si vous voulez le MAX ou le MIN (ou ajouter quelque chose à ORDER BY pour le rendre unique.)

(Si vous étiez sur Oracle version 12, une alternative à l'astuce KEEP (DENSE_RANK serait d'utiliser la clause FIRST 1 ROW ONLY de l'instruction SELECT.)