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 FSoui 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.