168 votes

LIMIT 10..20 in SQL Server

J'essaie de faire quelque chose comme :

SELECT * FROM table LIMIT 10,20

o

SELECT * FROM table LIMIT 10 OFFSET 10

mais en utilisant SQL Server

Le seul solution que j'ai trouvée c'est un peu exagéré :

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE row > 5 and row <= 10

J'ai aussi trouvé :

SELECT TOP 10 * FROM stuff; 

... mais ce n'est pas ce que je veux faire puisque je ne peux pas spécifier la limite de départ.

Y a-t-il un autre moyen de le faire ?

Par ailleurs, par curiosité, y a-t-il une raison pour laquelle le serveur SQL ne prend pas en charge l'option LIMIT ou quelque chose de similaire ? Je ne veux pas être méchant, mais cela ressemble vraiment à quelque chose dont un SGBD a besoin ... Si c'est le cas, alors je suis désolé d'être si ignorant ! Je travaille avec MySQL et SQL+ depuis 5 ans donc...

1 votes

Utilisation d'un CTE pour ROW_NUMBER() et en limitant avec TOP pour la largeur de la plage et un WHERE pour une limite de la plage est le meilleur résultat que j'ai pu obtenir. J'ai également remarqué que les performances étaient bien meilleures si le paramètre TOP utilise un littéral au lieu d'une variable

0 votes

Le problème avec toute solution impliquant ROW_NUMBER() est que si vous ne savez pas à l'avance quelles colonnes vous aurez, et que vous avez des jointures, et que les tables jointes ont le même nom de colonne, vous obtiendrez un "La colonne 'xxx' a été spécifiée plusieurs fois". Ce n'est pas aussi rare que cela puisse paraître. J'utilise Dapper, et mes tables ont toutes une colonne Id. Dapper divise et mappe sur cette colonne, je ne veux donc pas les renommer, mais je ne peux pas utiliser l'alias SELECT * FROM ([requête originale]). Je n'ai pas encore trouvé de solution !

0 votes

138voto

Martin Smith Points 174101

Pour SQL Server 2012 + vous pouvez utiliser .

SELECT  *
FROM     sys.databases
ORDER BY name 
OFFSET  5 ROWS 
FETCH NEXT 5 ROWS ONLY

10 votes

SQl Server 2012 exige de spécifier ORDER BY lorsque vous utilisez OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY alors que MySql et SQLite n'exigent pas ORDER BY lorsque vous utilisez LIMIT 5,5.

4 votes

@qub1n - MySQL ne garantit pas quels sont les rangs que vous récupérez dans ce cas.

3 votes

Devez-vous utiliser offset ou pouvez-vous laisser cette ligne de côté (en supposant que vous ne voulez pas de décalage) ?

111voto

Bill Karwin Points 204877

El LIMIT ne fait pas partie du langage SQL standard. Elle est prise en charge en tant qu'extension vendeur de SQL par MySQL, PostgreSQL et SQLite.

D'autres marques de bases de données peuvent avoir des caractéristiques similaires (par exemple, le système de gestion de la base de données). TOP dans Microsoft SQL Server), mais ils ne fonctionnent pas toujours de manière identique.

C'est difficile à utiliser TOP dans Microsoft SQL Server pour imiter le LIMIT clause. Il y a des cas où cela ne fonctionne tout simplement pas.

La solution que vous avez montrée, en utilisant ROW_NUMBER() est disponible à partir de Microsoft SQL Server 2005. Il s'agit de la meilleure solution (pour l'instant) qui fonctionne uniquement dans le cadre de la requête.

Une autre solution consiste à utiliser TOP pour récupérer le premier compter + décalage et ensuite utiliser l'API pour aller au-delà de la première ligne. décalage rangs.

Voir aussi :

36voto

KM. Points 51800

Comme vous l'avez constaté, c'est la méthode préférée de sql server :

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE a.row > 5 and a.row <= 10

0 votes

Pourquoi le a après la sélection interne ? Je suppose que vous donnez un alias à la sélection interne, mais vous ne semblez jamais l'utiliser... Devriez-vous alors faire a.row au lieu de simplement row ?

3 votes

@Lucas, vous êtes tenu de mettre un alias après l'élément ( ) mais il le laissera partir si vous oubliez ensuite de l'utiliser pour faire référence aux colonnes. Je l'ai corrigé cependant...

0 votes

Merci, je l'ai découvert à la dure (j'ai essayé de ne pas utiliser l'alias).

8voto

David Patrick Points 59

Que pensez-vous de ça ?

SET ROWCOUNT 10 

SELECT TOP 20 *
FROM sys.databases
ORDER BY database_id DESC

Il vous donne les 10 dernières lignes des 20 premières lignes. L'inconvénient est que l'ordre est inversé, mais au moins, c'est facile à retenir.

6 votes

Et s'il n'y a que 14 lignes dans le tableau ? Vous obtenez les rangées 14 à 5, ce qui n'est pas la même chose que les rangées renvoyées par LIMIT 10 OFFSET 10 (qui devraient être les rangées 14 à 11).

7voto

Joel Coehoorn Points 190579

Malheureusement, le ROW_NUMBER() est le mieux que vous puissiez faire. C'est en fait plus correct, parce que les résultats d'une limit o top Les clauses n'ont pas vraiment de sens sans le respect d'un ordre spécifique. Mais c'est quand même pénible à faire.

Mise à jour : Sql Server 2012 ajoute une limit -par l'intermédiaire de Mots clés OFFSET et FETCH . Il s'agit de l'approche normalisée ansi, par opposition à LIMIT qui est une extension MySql non standard.

0 votes

@Joel : Pouvez-vous expliquer pourquoi ROW_NUMBER() est incapable de numéroter les lignes de la manière dont elles sortent de ORDER BY ? Je me suis toujours demandé pourquoi le "OVER (ORDER BY name)" est obligatoire, mais je suppose qu'il y a une bonne raison à cela. Ou du moins a raison.

3 votes

Car il n'y a pas d'ordre sans clause d'ordre. Vous obtenez l'ordre dans lequel les enregistrements étaient disponibles sur le serveur, et cela pourrait changement de requête en requête.

0 votes

Mais je faisais explicitement référence à une clause ORDER BY. Supposons que la requête elle-même en possède une - pourquoi ROW_NUMBER() ne peut-elle pas se contenter de cela ? Je veux dire, quelle est la raison interne à la base de données qui m'oblige à modifier la requête en deux endroits si je veux en obtenir une tranche dans un ordre différent ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X