Requête SQLServer SQL avec un compteur de lignes

j'ai une requête SQL qui retourne un ensemble de lignes:

SELECT id, name FROM users where group = 2

j'ai besoin d'inclure également une colonne qui a une incrémentation valeur d'entier, de sorte que la première ligne doit avoir un 1 dans la colonne compteur, le deuxième 2 points, le troisième 3, etc

la requête montrée ici n'est qu'un exemple simplifié, en réalité la requête pourrait être arbitrairement complexe, avec plusieurs jointures et requêtes imbriquées.

je sais que cela pourrait être réalisé en utilisant une table temporaire avec un numéro d'auto champ, mais est-il un moyen de le faire dans la requête elle-même ?

19
demandé sur andynormancx 2009-01-29 20:52:21

4 réponses

Pour commencer, quelque chose le long des lignes de:

SELECT my_first_column, my_second_column,
    ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter
FROM my_table

cependant, il est important de noter que le ROW_NUMBER() OVER (ORDER BY ...) la construction ne détermine que les valeurs de Row_Counter, il ne garantit pas l'ordre des résultats.

sauf si le SELECT lui-même a une explicite ORDER BY clause, les résultats peuvent être retournés dans n'importe quel ordre, dépendant de la façon dont SQL Server décide d'optimiser la requête. (Voir cet article pour plus d'info.)

le seul moyen afin de garantir que les résultats toujours à retourner dans Row_Counter l'ordre doit appliquer exactement le même ordre aux deux SELECT et ROW_NUMBER():

SELECT my_first_column, my_second_column,
    ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter
FROM my_table
ORDER BY my_order_column  -- exact copy of the ordering used for Row_Counter

le modèle ci-dessus retournera toujours les résultats dans le bon ordre et fonctionne bien pour les requêtes simples, mais qu'en est-il d'une requête "arbitrairement complexe" avec peut-être des dizaines d'expressions dans le ORDER BY l'article? Dans ces situations, je préfère quelque chose comme ceci:

SELECT t.*
FROM
(
    SELECT my_first_column, my_second_column,
        ROW_NUMBER() OVER (ORDER BY ...) AS Row_Counter  -- complex ordering
    FROM my_table
) AS t
ORDER BY t.Row_Counter

à l'Aide d'un requête imbriquée signifie qu'il n'y a pas besoin de dupliquer l'compliqué ORDER BY clause, ce qui signifie moins d'encombrement et un entretien plus facile. L'extérieur ORDER BY t.Row_Counter rend également l'intention de la requête beaucoup plus claire pour vos collègues développeurs.

24
répondu LukeH 2009-02-06 09:54:44

Dans SQL Server 2005, vous pouvez utiliser le ROW_NUMBER() fonction, qui a des options pour l'ordre de tri et les groupes sur lesquels les comptes sont faits (et réinitialisés).

10
répondu Cade Roux 2009-01-29 18:20:02

la façon la plus simple est d'utiliser un compteur de lignes variable. Cependant ce serait deux commandes SQL réelles. L'un pour définir la variable, puis de la requête comme suit:

SET @n=0;
SELECT @n:=@n+1, a.* FROM tablename a

Votre requête peut être aussi complexe que vous le souhaitez avec des jointures etc. J'ai l'habitude de faire cela d'une procédure stockée. Vous pouvez avoir toutes sortes de plaisir avec la variable, même l'utiliser pour calculer l'encontre des valeurs de champ. La clé est le :=

2
répondu Clark Vera 2016-12-20 18:16:30

Heres une approche différente. Si vous avez plusieurs tables de données qui ne sont pas joignable, ou pour une raison, vous ne voulez pas compter toutes les lignes en même temps, mais vous voulez continuer à faire partie du même nombre de lignes, vous pouvez créer une table qui fait le travail pour vous.

Exemple:

create table #test (
        rowcounter int identity,
        invoicenumber varchar(30)
        )

insert into #test(invoicenumber) select [column] from [Table1]

insert into #test(invoicenumber) select [column] from [Table2]

insert into #test(invoicenumber) select [column] from [Table3]

select * from #test

drop table #test
-3
répondu Rasmus 2016-03-01 20:43:16