web-dev-qa-db-fra.com

LIMIT 10..20 dans SQL Server

J'essaie de faire quelque chose comme:

SELECT * FROM table LIMIT 10,20

ou

SELECT * FROM table LIMIT 10 OFFSET 10

mais en utilisant SQL Server

Le seul solution que j'ai trouvée ressemble à un excès:

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 car je ne peux pas spécifier la limite de départ.

Y a-t-il un autre moyen pour moi de faire cela?

Aussi, juste curieux, y a-t-il une raison pour laquelle SQL Server ne prend pas en charge la fonction 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, je suis désolé d'être aussi ignorant! Je travaille avec MySQL et SQL + depuis 5 ans, alors ...

154
marcgg

La clause LIMIT ne fait pas partie du SQL standard. Il est supporté comme extension de fournisseur à SQL par MySQL, PostgreSQL et SQLite.

D'autres marques de base de données peuvent avoir des fonctionnalités similaires (par exemple, TOP dans Microsoft SQL Server), mais celles-ci ne fonctionnent pas toujours de manière identique.

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

La solution que vous avez présentée à l’aide de ROW_NUMBER() est disponible dans Microsoft SQL Server 2005 et versions ultérieures. C'est la meilleure solution (pour l'instant) qui fonctionne uniquement dans le cadre de la requête.

Une autre solution consiste à utiliser TOP pour extraire le premier nombre + offset lignes, puis utilisez l’API pour rechercher au-delà des premières décalées lignes.

Voir également:

100
Bill Karwin

Pour SQL Server 2012 + vous pouvez utiliser .

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

comme vous l'avez constaté, il s'agit de la méthode de serveur SQL préférée:

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

Si vous utilisez SQL Server 2012+, votez pour réponse de Martin Smith et utilisez les extensions OFFSET et FETCH NEXT de ORDER BY,

Si vous êtes assez malheureux pour vous retrouver avec une version antérieure, vous pouvez faire quelque chose comme ça,

WITH Rows AS
(
    SELECT
              ROW_NUMBER() OVER (ORDER BY [dbo].[SomeColumn]) [Row]
            , *
        FROM
              [dbo].[SomeTable]
)
SELECT TOP 10
          *
     FROM
         Rows
    WHERE Row > 10

Je crois est fonctionnellement équivalent à

SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn

et le moyen le plus performant que je connaisse de le faire dans TSQL, avant MS SQL 2012.


S'il y a beaucoup de lignes, vous obtiendrez de meilleures performances en utilisant une table temporaire au lieu d'un CTE.

10
Jodrell

Malheureusement, la ROW_NUMBER() est ce que vous pouvez faire de mieux. C'est en fait plus correct, car les résultats d'une clause limit ou top n'ont pas vraiment de sens sans respecter un ordre spécifique. Mais c'est toujours pénible à faire.

Mise à jour: Sql Server 2012 ajoute une fonctionnalité de type limit via mots-clés OFFSET et FETCH . C'est l'approche ansi-standard, par opposition à LIMIT, qui est une extension MySql non standard.

7
Joel Coehoorn

Que dis-tu 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. Un inconvénient est que l'ordre est inversé, mais au moins, il est facile de s'en souvenir.

5
David Patrick
SELECT TOP 10 *
FROM TABLE
WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE)

Devrait donner des enregistrements 11-20. Probablement pas trop efficace si incrémenté pour obtenir des pages supplémentaires, et pas sûr de savoir comment cela pourrait être affecté par la commande. Vous devrez peut-être spécifier cela dans les deux instructions WHERE.

2
Andy

Juste pour la solution d'enregistrement qui fonctionne sur la plupart des moteurs de base de données, elle pourrait ne pas être la plus efficace:

Select Top (ReturnCount) *
From (
    Select Top (SkipCount + ReturnCount) *
    From SourceTable
    Order By ReverseSortCondition
) ReverseSorted
Order By SortCondition

Note Pelase: la dernière page contiendrait toujours des lignes ReturnCount, quel que soit SkipCount. Mais cela pourrait être une bonne chose dans de nombreux cas.

1
Y.B.

Un bon moyen est de créer une procédure:

create proc pagination (@startfrom int ,@endto int) as
SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name desc) as row FROM sys.databases 
 ) a WHERE a.row > @startfrom and a.row <= @endto

comme limite 0,2 /////////////// exécuter la pagination 0,4

1
Wahaj Latif

L'équivalent de LIMIT est SET ROWCOUNT, mais si vous voulez une pagination générique, il est préférable d'écrire une requête comme celle-ci:

;WITH Results_CTE AS
(
    SELECT
        Col1, Col2, ...,
        ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
    FROM Table
    WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= @Offset
AND RowNum < @Offset + @Limit
1

Utilisez tous les serveurs SQL:; avec tbl comme (SELECT ROW_NUMBER () sur (ordre de (sélectionnez 1)) comme RowIndex, * du tableau), sélectionnez Top 10 * à partir de tbl où RowIndex> = 10

0
Phạm Tấn Lợi

Dans la documentation en ligne de MS SQL Server ( http://technet.Microsoft.com/en-us/library/ms186734.aspx ), voici l’exemple que j’ai testé et qui fonctionne pour récupérer une ensemble spécifique de lignes. ROW_NUMBER nécessite un OVER, mais vous pouvez commander ce que vous voulez:

WITH OrderedOrders AS
(
  SELECT SalesOrderID, OrderDate,
  ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
  FROM Sales.SalesOrderHeader 
) 
SELECT SalesOrderID, OrderDate, RowNumber  
FROM OrderedOrders 
WHERE RowNumber BETWEEN 50 AND 60;
0
Shannon WM

Jusqu'à présent, ce format est ce qui fonctionne pour moi (pas la meilleure performance cependant):

SELECT TOP {desired amount of rows} * 
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY {order columns} asc)__row__ FROM {table})tmp
WHERE __row__ > {offset row count}

Une note sur le côté, paginant sur des données dynamiques peut conduire à des résultats étranges/inattendus.

0
Charlie Affumigato
select * from (select id,name,ROW_NUMBER() OVER (ORDER BY id  asc) as row
from tableName1) tbl1
where tbl1.row>=10 and tbl1.row<=15

Imprimera les lignes de 10 à 15.

0
sjith