web-dev-qa-db-fra.com

Comment implémenter LIMIT avec Microsoft SQL Server?

J'ai cette requête avec mysql: 

select * from table1 LIMIT 10,20

Comment puis-je faire cela avec Microsoft SQL?

106
Bigballs

À partir de SQL SERVER 2005, vous pouvez le faire ...

USE AdventureWorks;
GO
WITH OrderedOrders AS
(
    SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
    FROM Sales.SalesOrderHeader 
) 
SELECT * 
FROM OrderedOrders 
WHERE RowNumber BETWEEN 10 AND 20;

ou quelque chose comme ça pour les versions 2000 et inférieures ...

SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC
105
Leon Tayson

Clunky, mais ça va marcher.

SELECT TOP 10 * FROM table WHERE id NOT IN (SELECT TOP 10 id FROM table ORDER BY id) FROM table ORDER BY id

L'omission par MSSQL d'une clause LIMIT est criminelle, IMO. Vous ne devriez pas avoir à faire ce genre de solution de contournement.

47
ceejayoz

À partir de SQL SERVER 2012, vous pouvez utiliser la clause OFFSET FETCH:

USE AdventureWorks;
GO
SELECT SalesOrderID, OrderDate
FROM Sales.SalesOrderHeader 
ORDER BY SalesOrderID
    OFFSET 10 ROWS
    FETCH NEXT 10 ROWS ONLY;
GO

http://msdn.Microsoft.com/en-us/library/ms188385(v=sql.110).aspx

Cela peut ne pas fonctionner correctement lorsque la commande de n'est pas unique.

Si la requête est modifiée en ORDER BY OrderDate, le jeu de résultats renvoyé n'est pas celui attendu.

24
user4047259

C’est presque une copie d’une question que j’avais posée en octobre: ​​ Emulate MySQL LIMIT clause dans Microsoft SQL Server 2000

Si vous utilisez Microsoft SQL Server 2000, il n'y a pas de bonne solution. La plupart des gens doivent capturer le résultat de la requête dans une table temporaire avec une clé primaire IDENTITY. Interrogez ensuite la colonne de clé primaire en utilisant une condition BETWEEN.

Si vous utilisez Microsoft SQL Server 2005 ou une version ultérieure, vous disposez d'une fonction ROW_NUMBER(). Vous pouvez ainsi obtenir le même résultat mais éviter la table temporaire.

SELECT t1.*
FROM (
    SELECT ROW_NUMBER OVER(ORDER BY id) AS row, t1.*
    FROM ( ...original SQL query... ) t1
) t2
WHERE t2.row BETWEEN @offset+1 AND @offset+@count;

Vous pouvez également écrire ceci sous la forme d'une expression de table common , comme indiqué dans le answer de @Leon Tayson.

18
Bill Karwin
SELECT  *
FROM    (
        SELECT  TOP 20
                t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
        FROM    table1 t
        ORDER BY
                field1
        ) t
WHERE   rn > 10
12
Quassnoi

Voici comment je limite les résultats dans MS SQL Server 2012

SELECT * 
FROM table1
ORDER BY columnName
  OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

REMARQUE: OFFSET ne peut être utilisé qu'avec ORDER BY.

Pour expliquer la ligne de code OFFSET xx ROWS FETCH NEY yy ROW ONLY

Le "xx" est le numéro d'enregistrement/ligne que vous voulez commencer à extraire dans la table .
IE: S'il y a 40 enregistrements dans la table 1. Le code ci-dessus commencera à extraire de la ligne 10.

Le "yy" est le nombre d'enregistrements/lignes que vous voulez extraire de la table .
Pour construire sur l'exemple précédent. 
IE: Si la table 1 contient 40 enregistrements et que vous avez commencé à extraire de la ligne 10, vous avez saisi l'ensemble NEXT de 10 (yy). 
Cela signifie que le code ci-dessus extraira les enregistrements de la table 1 en commençant par la ligne 10 et en finissant par 20. Ainsi, en extrayant les lignes 10 à 20.

Consultez le lien pour plus d'informations sur OFFSET

11
Jeremy

Syntaxiquement, la requête MySQL LIMIT ressemble à ceci:

SELECT * FROM table LIMIT OFFSET, ROW_COUNT

Ceci peut être traduit en Microsoft SQL Server comme

SELECT * FROM 
(
    SELECT TOP #{OFFSET+ROW_COUNT} *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum 
    FROM table
) a
WHERE rnum > OFFSET

Maintenant, votre requête select * from table1 LIMIT 10,20 sera comme ceci:

SELECT * FROM 
(
    SELECT TOP 30 *, ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS rnum 
    FROM table1
) a
WHERE rnum > 10 
8
user1134160

C'est l'une des raisons pour lesquelles j'essaie d'éviter d'utiliser MS Server ... mais de toute façon. Parfois, vous n'avez simplement pas d'option (yei! Et je dois utiliser une version obsolète !!).

Ma suggestion est de créer une table virtuelle:

De:

SELECT * FROM table

À:

CREATE VIEW v_table AS    
    SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS row,* FROM table

Ensuite, il suffit d'interroger:

SELECT * FROM v_table WHERE row BETWEEN 10 AND 20

Si des champs sont ajoutés ou supprimés, "row" est mis à jour automatiquement.

Le principal problème de cette option est que ORDER BY est corrigé. Donc, si vous voulez un ordre différent, vous devrez créer une autre vue.

METTRE À JOUR

Il existe un autre problème avec cette approche: si vous essayez de filtrer vos données, cela ne fonctionnera pas comme prévu. Par exemple, si vous le faites: 

SELECT * FROM v_table WHERE field = 'test' AND row BETWEEN 10 AND 20

WHERE devient limité aux données contenues dans les lignes comprises entre 10 et 20 (au lieu de rechercher l'ensemble du jeu de données et de limiter la sortie).

2
lepe
SELECT 
    * 
FROM 
    (
        SELECT 
            top 20              -- ($a) number of records to show
            * 
        FROM
            (
                SELECT 
                    top 29      -- ($b) last record position
                    * 
                FROM 
                    table       -- replace this for table name (i.e. "Customer")
                ORDER BY 
                    2 ASC
            ) AS tbl1 
        ORDER BY 
            2 DESC
    ) AS tbl2 
ORDER BY 
    2 ASC;

-- Examples:

-- Show 5 records from position 5:
-- $a = 5;
-- $b = (5 + 5) - 1
-- $b = 9;

-- Show 10 records from position 4:
-- $a = 10;
-- $b = (10 + 4) - 1
-- $b = 13;

-- To calculate $b:
-- $b = ($a + position) - 1

-- For the present exercise we need to:
-- Show 20 records from position 10:
-- $a = 20;
-- $b = (20 + 10) - 1
-- $b = 29;
1
Julian Moreno

Il s’agit d’une approche en plusieurs étapes qui fonctionnera sous SQL2000.

-- Create a temp table to hold the data
CREATE TABLE #foo(rowID int identity(1, 1), myOtherColumns)

INSERT INTO #foo (myColumns) SELECT myData order By MyCriteria

Select * FROM #foo where rowID > 10
1
souLTower

mieux l'utiliser dans MSSQLExpress 2017.

SELECT * FROM
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as [Count], * FROM table1
) as a
WHERE [Count] BETWEEN 10 and 20;

- Donner une colonne [Count] et attribuer à chaque ligne un comptage unique sans rien commander, puis sélectionner à nouveau où vous pouvez indiquer vos limites .. :)

0
user1308314

En SQL, il n'y a pas de mot clé LIMIT. Si vous n'avez besoin que d'un nombre limité de lignes, vous devez utiliser un mot clé TOP similaire à un mot LIMIT.

0
Mitul Panchal

Dois essayer. Dans la requête ci-dessous, vous pouvez voir group by, order by, Ignorer les lignes et les limiter.

select emp_no , sum(salary_amount) from emp_salary
Group by emp_no 
ORDER BY emp_no 
OFFSET 5 ROWS       -- Skip first 5 
FETCH NEXT 10 ROWS ONLY; -- limit to retrieve next 10 row after skiping rows
0
M Danish

Si votre identifiant est un identifiant unique ou si votre identifiant dans la table n'est pas trié, procédez comme suit:

select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5



Le code sera 

sélectionnez * de la limite 2,5
0
user3244012