J'utilise une requête de mise à jour dans laquelle j'utilise une variable externe dans une sous-requête imbriquée, mais je trouve une erreur:
Erreur SQL: ORA-00904: "FS". "GR_NUMBER": identifiant invalide
update table fs set fs.branch_id= (select branch_id from (select branch_id,row_number() over(PARTITION by gr_number order by updated_ts desc) as Sno from admission_log where gr_number=fs.gr_number ) where sno=1) ;
3 Réponses :
Le problème avec votre requête est que vous essayez d'accéder à la colonne fs.gr_number
dans une sous-requête de deux niveaux plus bas. Vous ne pouvez accéder qu'à la colonne de niveau supérieur d'une sous-requête d'un niveau plus bas.
Votre déclaration doit être:
MERGE INTO fs tgt USING (SELECT branch_id, row_number() OVER (PARTITION BY gr_number ORDER BY updated_ts DESC) AS sno FROM admission_log) src ON (tgt.gr_number = src.gr_number AND src.sno = 1) WHEN MATCHED THEN UPDATE tgt.branch_id = src.branch_id;
Cela déplace la corrélation d'un niveau vers le bas. Notez comment j'ai également aliasé la sous-requête imbriquée.
Les performances ne devraient pas être terribles, car le prédicat x.gr_number = fs.gr_number
implique la même colonne dans la sous-requête sur lequel la fonction analytique est partitionnée. Cela devrait permettre à Oracle de filtrer la sous-requête de manière appropriée.
ETA: vous pouvez également utiliser une instruction MERGE à la place:
UPDATE fs SET fs.branch_id = (SELECT branch_id FROM (SELECT branch_id, gr_number, row_number() OVER (PARTITION BY gr_number ORDER BY updated_ts DESC) AS sno FROM admission_log) x WHERE x.gr_number = fs.gr_number AND sno = 1);
(J'ai annulé la question et j'ai demandé à l'auteur de la question de publier une nouvelle question).
Comme il s'agit d'Oracle, vous pouvez utiliser une clause de fusion et utiliser la fonction min () pour obtenir la valeur au lieu de la fonction row_number ().
update table fs set fs.branch_id= (select branch_id from (select branch_id,row_number() over(PARTITION by gr_number order by updated_ts desc) as Sno from admission_log) where sno=1 and gr_number=fs.gr_number) ;
Si vous vouliez toujours utiliser la fonction roe_number (), ci-dessous se trouve la requête. Votre clause WHERE pour rejoindre la table doit être en dehors de la sous-requête.
merge into table fs using (select gr_number, min(branch_id) as branch_id from admission_log) qry on (fx.gr_number = qry.gr_number) when matched then update set fs.branch_id = qry.branch_id;
min (branch_id)
ne donnera pas nécessairement le bon résultat.
Pourquoi pas, vous prenez rownum = 1, ici son min (branch_id). Quelle différence cela fait? Regrouper gr_number par rapport à min (branch_id) donnera le même résultat que de prendre le rownum = 1. S'il veut prendre autre chose que le numéro de la 1ère ligne, min (branch_id) n'a pas de sens
La fonction analytique recherche le dernier branch_id en fonction de la dernière valeur updated_ts. Si le branch_id de la dernière ligne est 10, mais qu'une ligne précédente en a 5, votre min (branch_id)
renverra une valeur incorrecte.
(J'ai annulé la question et j'ai demandé à l'auteur de la question de publier une nouvelle question).
Utilisez ce code:
update fs a set a.branch_id = (select c.branch_id from (select b.branch_id, row_number() over(PARTITION by b.gr_number order by b.updated_ts desc) as Sno from admission_log b where b.gr_number = a.gr_number) c where c.sno = 1);
La table FS a-t-elle le nom de colonne
GR_NUMBER
? Votre requête me semble correcte. Veuillez fournir la sortie duDESC FS
oui la table fs a la colonne GR_NUMBER
je modifie ma question s'il vous plaît regarder cette erreur ..
J'ai ramené cette question à sa version antérieure. Les questions ne doivent pas être modifiées avec une nouvelle version où les réponses ont été données, car cela invalide les réponses existantes. Veuillez poser une nouvelle question pour votre nouveau problème.