comment puis-je mettre à jour les 100 meilleurs enregistrements dans le serveur SQL

393

Je souhaite mettre à jour les 100 meilleurs enregistrements dans SQL Server. J'ai une table T1avec des champs F1et F2. T1a 200 enregistrements. Je souhaite mettre à jour le F1champ dans les 100 premiers enregistrements. Comment puis-je mettre à jour en fonction de TOP 100dans SQL Server?

Rajesh
la source

Réponses:

684

Remarque, les parenthèses sont obligatoires pour les instructions UPDATE:

update top (100) table1 set field1 = 1
Umair Ahmed
la source
28
Une idée de comment l'utiliser order byaussi?
Joe Phillips
8
@JoePhilllips Utilisez la réponse de Martin Smith pour la commande par
jjxtra
Ce ne sont pas les 100 premiers enregistrements, mais simplement 100 enregistrements choisis arbitrairement. Le top 100 inclurait un ordre de classement des records.
Thorsten Kettner
1
Cela répond à la question "comme demandé" mais TOP n'a aucun sens (et imprévisible) sans quelque ORDRE. Voir la réponse plus loin par Martin Smith.
Andy G
1
btw: les parenthèses sont importantes!
Simon_Weaver
300

Sans un ORDER BYtout, l'idée de TOPn'a pas beaucoup de sens. Vous devez avoir une définition cohérente de la direction «vers le haut» et de la direction «vers le bas» pour que le concept de sommet soit significatif.

Néanmoins, SQL Server le permet mais ne garantit pas un résultat déterministe .

La UPDATE TOPsyntaxe dans la réponse acceptée ne prend pas en charge une ORDER BYclause mais il est possible d'obtenir ici une sémantique déterministe en utilisant un CTE ou une table dérivée pour définir l'ordre de tri souhaité comme ci-dessous.

;WITH CTE AS 
( 
SELECT TOP 100 * 
FROM T1 
ORDER BY F2 
) 
UPDATE CTE SET F1='foo'
Martin Smith
la source
71
Vous dites vide de sens mais ce n'est pas vrai. J'admets que, généralement /, lorsque vous utilisez des TOPcotes, vous devriez l'utiliser avec ORDER BYparce que ce qui vous intéresse est comme le "plus" ou "le moins" de quelque chose. Dans d'autres cas, cependant, il se peut que vous ne souhaitiez obtenir qu'un seul enregistrement correspondant. Comme moi aujourd'hui! J'avais besoin de résoudre les problèmes de données (cycles) un à la fois. L'ensemble du processus de correction impliquait un script db, une intervention de l'utilisateur et certaines opérations d'application. Peu nous importait quel enregistrement a été traité en premier. Nous voulions juste que nous les manipulions un à la fois.
MetaFight
17
@MetaFight Mais vous auriez alors eu une WHEREclause pour exclure les enregistrements précédemment traités. La question telle que la réponse écrite et acceptée n'a pas de sens. BTW: Pour utiliser des tables comme file d'attente, c'est un lien très utile
Martin Smith
10
J'ai besoin d'utiliser top sans ordre pour pouvoir exécuter un processus asynchrone. La clause where n'inclura pas ceux qui ont déjà été traités, mais je ne peux en traiter qu'un grand nombre à la fois. Il a donc un cas d'utilisation parfaitement valide.
Jeff Davis
4
@Martin Smith: Disons que vous voulez mettre à jour par lots, disons 10000 à la fois. Cela semble être une bonne utilisation pour cela, et l'ordre n'a pas d'importance. Comment cela "n'a pas de sens"?
Jay Sullivan
5
@notfed C'est le même cas que celui qui a déjà été discuté à mort dans les commentaires ci-dessus. Dans ce cas, votre requête ne ressemblerait pas à celle de la réponse acceptée, n'est-ce pas? Vous auriez besoin d'une whereclause pour éviter de traiter les mêmes lignes encore et encore.
Martin Smith
14

pour ceux comme moi toujours bloqués avec SQL Server 2000, SET ROWCOUNT {number};peut être utilisé avant la UPDATErequête

SET ROWCOUNT 100;
UPDATE Table SET ..;
SET ROWCOUNT 0;

limitera la mise à jour à 100 lignes

Il est obsolète au moins depuis SQL 2005, mais depuis SQL 2017, il fonctionne toujours. https://docs.microsoft.com/en-us/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017

Claudio B
la source
1
SET ROWCOUNT affecte les déclencheurs ainsi que la commande en cours de mise à jour. Si vous avez défini un ensemble de suppressions en cascade, la transaction peut échouer si le nombre de lignes enfants dépasse la table enfant.
EricI
Cela dit, SET ROWCOUNT @RowCountParameter; est une syntaxe valide, tandis que SELECT TOP @RowCountParamter * FROM TableName n'est pas valide. Si vous devez configurer les lignes en cours de mise à jour, SET ROWCOUNT # est actuellement la meilleure option, à condition que vous n'ayez pas de tables enfants avec la suppression en cascade activée.
EricI
Dans SQL Server 2017, il est désormais possible d'utiliser @variable dans la clause TOP: docs.microsoft.com/en-us/sql/t-sql/queries/…
Alexandr Zarubkin
13
update tb set  f1=1 where id in (select top 100 id from tb where f1=0)
hyyxing
la source
4

Ce qui est encore plus cool, c'est le fait que vous pouvez utiliser une fonction de valeur de table en ligne pour sélectionner la (et le nombre via TOP) ligne (s) à mettre à jour. C'est:

UPDATE MyTable
SET Column1=@Value1
FROM tvfSelectLatestRowOfMyTableMatchingCriteria(@Param1,@Param2,@Param3)

Pour la fonction table, vous avez quelque chose d'intéressant pour sélectionner la ligne à mettre à jour comme:

CREATE FUNCTION tvfSelectLatestRowOfMyTableMatchingCriteria
(
    @Param1 INT,
    @Param2 INT,
    @Param3 INT
)
RETURNS TABLE AS RETURN
(
    SELECT TOP(1) MyTable.*
    FROM MyTable
    JOIN MyOtherTable
      ON ...
    JOIN WhoKnowsWhatElse
      ON ...
    WHERE MyTable.SomeColumn=@Param1 AND ...
    ORDER BY MyTable.SomeDate DESC
)

... et il y a (à mon humble avis) le vrai pouvoir de ne mettre à jour que les premières lignes sélectionnées de manière déterministe tout en simplifiant la syntaxe de l' UPDATEinstruction.

Michael Goldshteyn
la source
0

Essayer:

UPDATE Dispatch_Post
SET isSync = 1
WHERE ChallanNo 
IN (SELECT TOP 1000 ChallanNo FROM dbo.Dispatch_Post ORDER BY 
CreatedDate DESC)
Shahin Al Kabir Mitul
la source
0

Vous pouvez également mettre à jour à partir de select en utilisant un alias et rejoindre:

UPDATE  TOP (500) T
SET     T.SomeColumn = 'Value'
FROM    SomeTable T
        INNER JOIN OtherTable O ON O.OtherTableFK = T.SomeTablePK
WHERE   T.SomeOtherColumn = 1
Vanderlei Pires
la source