2017-09-27 2 views
0

Oui, SQL UPDATE peut être utilisé avec order by dans une sous-requête SELECT.SQL Update avec besoin de commander dans la sous-requête

Tout le monde là-bas qui a une solution de contournement pour problème suivant:

De temps en temps un programme génère des erreurs de données dans TABLE1 (nous ne sommes pas propriétaire de ce code, mais besoin d'utiliser le programme ...)

Nous utilisons un déclencheur qui protocole toutes les modifications apportées à une table AUDIT.

Nous pouvons trouver la situation d'erreur (et l'ancienne valeur correcte) avec suivante, sélectionnez:

select top 1 audit.OldValue 
    from TABLE1 
    left join AUDIT on AUDIT.Table1_ID = TABLE1.ID 
where <...some conditions...> 
    order by AUDIT.UpdateDate desc 

Comme il y a plusieurs changements enregistrés, nous avons seulement besoin du dernier changement (order by updatedate puis prendre TOP 1)

nous corriger l'erreur de données, si nous pouvions utiliser la commande UPDATE comme

Update TABLE1 
set VALUE = 
(select top 1 audit.OldValue 
    from TABLE1 
    left join AUDIT on AUDIT.Table1_ID = TABLE1.ID 
    where <...some conditions...> 
    order by AUDIT.UpdateDate desc) 
where TABLE1.ID = AUDIT.Table1_ID 

MAIS: vous ne pouvez pas utiliser le order by dans une sous-requête ...

+0

Quels sont les dbms que vous utilisez? – jarlh

+0

Copie possible de [Comment mettre à jour la colonne provenant du top 1 de l'autre table] (https://stackoverflow.com/questions/6952277/how-to-update-the-column-coming-from-top-1-of -other-table) – Prisoner

+0

Nous utilisons MS-SQL-Server 2012 –

Répondre

0

J'ai changé le UPDATE -command à:

Update TABLE1 
set VALUE = CORRECT_VALUES.OldValue 
from 
(select top 1 audit.OldValue OldValue, AUDIT.Table1_ID Table1_ID 
    from TABLE1 
    left join AUDIT on AUDIT.Table1_ID = TABLE1.ID 
    where <...some conditions...> 
    order by AUDIT.UpdateDate desc) as CORRECT_VALUES 
where TABLE1.ID = CORRECT_VALUES.Table1_ID 

Cela fonctionne très bien.

Et comme cela ne change 1 entrée (en raison de TOP 1) nous devons utiliser une boucle:

Declare @i int = 0 
Declare @NUMBER int = (select count(*) from 
    (select distinct AUDIT.Table1_ID 
     from TABLE1 
     left join AUDIT on AUDIT.Table1_ID = TABLE1.ID 
    where <...some conditions...> 
    )) 

while @i < @NUMBER 
BEGIN 
    SET @i = @i + 1 
    <... past the whole UPDATE command here ...> 
END 

fonctionne très bien pour tous les documents qui doivent être mis à jour.

Soyez conscient du distict car il peut y avoir beaucoup de changements pour le même ID et vous avez seulement besoin de changer les enregistrements.

0

Au lieu d'utiliser top 1ROW_NUMBER() et de garder uniquement les lignes où il est =1

quelque chose comme:

Update t set Value = A.OldValue 
FROM Table1 t 
inner join (
    select ROW_NUMBER() OVER (PARTITION BY UserCode ORDER BY MEASUREDATE DESC) N, Id Table1_ID, * 
    from AUDIT 
) a on a.Table1_ID = t.ID 
where <...some conditions...> 
AND (a.N=1) 

Vous appliquerez toutes les mises à jour de tous les enregistrements avec une seule mise à jour (attention à < .. .some conditions ...>)