0
votes

Comment utiliser une variable de requête externe dans une sous-requête imbriquée à l'aide de la mise à jour

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) ;


4 commentaires

La table FS a-t-elle le nom de colonne GR_NUMBER ? Votre requête me semble correcte. Veuillez fournir la sortie du DESC 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.


3 Réponses :


1
votes

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);


1 commentaires

(J'ai annulé la question et j'ai demandé à l'auteur de la question de publier une nouvelle question).



-1
votes

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;


4 commentaires

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



0
votes

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);


0 commentaires