2009-03-02 7 views
85

J'ai cette requête avec MySQL:Comment implémenter LIMIT avec Microsoft SQL Server?

select * from table1 LIMIT 10,20 

Comment puis-je faire avec Microsoft SQL?

+0

duplication possible de [LIMIT 10..20 dans SQL Server] (http://stackoverflow.com/questions/971964/limit-10-20-in-sql-server) – assylias

+10

Comme cette question a été posée en premier, wouldn L'autre question n'est-elle pas le double? –

+0

Voir: [Devrais-je signaler une question comme doublon si elle a reçu de meilleures réponses?] (Https://meta.stackoverflow.com/q/251938/55075) – kenorb

Répondre

94

A partir 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 2000 et au-dessous des versions ...

SELECT TOP 10 * FROM (SELECT TOP 20 FROM Table ORDER BY Id) ORDER BY Id DESC 
+5

La deuxième requête échoue si vous avez, par exemple, 14 lignes dans le tableau. Il vous donne les lignes 5 à 14, mais vous voulez les lignes 11 à 14. En général, il échoue pour la dernière "page" d'un résultat, sauf si le nombre total de lignes est un multiple de cette taille "page". –

+0

Vous avez raison ... ne l'avez pas testé :) –

+84

Une chose si simple doit être rendue si difficile par MS encore une fois! – Martin

-6
SELECT TOP 10 * FROM table; 

est le même que

SELECT * FROM table LIMIT 0,10; 

Here's an article about implementing Limit in MsSQL Son une __gVirt_NP_NN_NNPS<__ lecture agréable, spécialement les commentaires.

+1

Merci, mais je veux le record entre 10 et 20, il y a un moyen de le faire? – Bigballs

+1

ce_nely ever_ obtient les lignes du début du jeu de résultats ... –

+2

Cette réponse ne répond pas à la question d'origine, mais il est utile si quelqu'un comme moi a besoin de savoir comment obtenir les premiers résultats N et que vous avez obtenu ici via google etc ... – brianlmerritt

41

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 de MSSQL d'une clause LIMIT est criminelle, IMO. Vous ne devriez pas avoir à faire ce genre de contournement kludgy.

+0

Avez-vous une autre suggestion pour contourner ce problème? – Bigballs

+0

J'ai fait beaucoup de Google la dernière fois que j'ai dû faire face à MSSQL et c'était la meilleure solution que j'ai trouvée. Pas agréable, mais ça marche. – ceejayoz

+0

Cette solution fonctionne uniquement si le jeu de résultats contient une colonne unique. Ce n'est pas une solution générale pour imiter LIMIT pour n'importe quelle requête. –

-2

Si je me souviens bien (il a été un tandis que depuis que je tamponnai avec SQL Server), vous pourrez peut-être utiliser quelque chose comme ceci: (2005 et jusqu'à)

SELECT 
    * 
    ,ROW_NUMBER() OVER(ORDER BY SomeFields) AS [RowNum] 
FROM SomeTable 
WHERE RowNum BETWEEN 10 AND 20 
+0

SQL Server 2012: Msg 207, niveau 16, état 1, ligne 5 Nom de colonne incorrect 'RowNum'. –

+0

semble que vous avez une faute de frappe dans votre déclaration quelque part. RowNum est le nom que nous affectons à l'expression. Postez votre problème avec la source et la communauté vous aidera – Kris

+0

Cette syntaxe n'est pas valide. Vous ne pouvez pas référencer dans 'WHERE' un alias défini dans le même niveau' SELECT' clause. –

18

C'est al le plus d'un double d'une question que j'ai posée en octobre: ​​ Emulate MySQL LIMIT clause in Microsoft SQL Server 2000

Si vous utilisez Microsoft SQL Server 2000, il n'y a pas de bonne solution. La plupart des personnes doivent recourir à la capture du résultat de la requête dans une table temporaire avec une clé primaire IDENTITY. Puis interrogez la colonne de clé primaire en utilisant une condition BETWEEN.

Si vous utilisez Microsoft SQL Server 2005 ou version ultérieure, vous avez une fonction ROW_NUMBER(), vous pouvez donc 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 @[email protected]; 

Vous pouvez également écrire cela comme un common table expression comme indiqué dans @Leon Tayson de answer.

+0

ROW_NUMBER() OVER (ORDER BY) obtient des points pour être valide dans ANSI SQL: 2003, bien que la prise en charge dans les SGBD autres que SQL Server soit très inégale. Et c'est assez maladroit bien sûr ... – bobince

+0

@bobince: Il s'avère qu'Oracle, Microsoft SQL Server 2005, IBM DB2 et PostgreSQL 8.4 prennent en charge toutes les fonctions de la fenêtre. Cela couvre une énorme majorité du marché SQL. Le support est seulement irrégulier si vous utilisez MySQL, SQLite ou une ancienne version de la base de données ci-dessus. –

11
SELECT * 
FROM (
     SELECT TOP 20 
       t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn 
     FROM table1 t 
     ORDER BY 
       field1 
     ) t 
WHERE rn > 10 
+0

Eh bien, je viens de vérifier, SQL Server s'est avéré assez intelligent pour s'arrêter sur les conditions ROW_NUMBER(), s'il y a une colonne indexée dans la clause ORDER BY. – Quassnoi

1

Il s'agit d'une approche en plusieurs étapes qui fonctionnera dans 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 
8

Syntaxiquement MySQL LIMIT requête est quelque chose comme ceci:

SELECT * FROM table LIMIT OFFSET, ROW_COUNT 

Cela peut se traduire dans 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 
1
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; 
+0

Était une excellente solution pour moi. – Tyde

2

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 tout 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 

Pour:

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

Ensuite, il suffit requête:

SELECT * FROM v_table WHERE row BETWEEN 10 AND 20 

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

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

MISE À JOUR

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

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

OU devient limitée à ces données qui sont dans les lignes 10 à 20 (au lieu de rechercher l'ensemble des données et de limiter la sortie).

16

À partir de SQL Server 2012, vous pouvez utiliser le OFFSET FETCH article:

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 l'ordre de n'est pas unique.

Si la requête est modifiée à ORDER BY OrderDate, le jeu de résultats renvoyé n'est pas comme prévu.

+0

L'utilisation de 'with' nécessite seulement la moitié du temps pour terminer l'interrogation - voir la réponse de @Leon Tayson. Je n'ai aucune idée de ce que Microsoft a fait pour que ça devienne aussi lent. – isHuman

+0

Pourquoi cette réponse n'est-elle pas acceptée? Nous sommes en ** 2018 ** pour pleurer à haute voix! – Skipper

8

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 

NOTE: OFFSET ne peut être utilisé avec ou en tandem à l'ordre par.

Pour expliquer la ligne de code xx OFFSET FETCH SUIVANT RANGS LIGNE SEULEMENT yy

Le « xx » est le numéro d'enregistrement/ligne que vous souhaitez commencer à tirer à partir de la table.
IE: S'il y a 40 enregistrement dans le tableau 1. Le code ci-dessus commencera à tirer de la ligne 10.

Le « yy » est le nombre d'enregistrements/lignes que vous voulez tirer de la table.
Pour construire sur l'exemple précédent.
IE: Si le tableau 1 contient 40 enregistrements, vous avez commencé à tirer à partir de la ligne 10 et à saisir l'ensemble SUIVANT de 10 (yy).
Cela signifierait, le code ci-dessus va tirer les enregistrements de la table 1 à partir de la ligne 10 et se terminant à 20. Ainsi, en tirant des lignes 10 - 20.

Consultez le lien pour plus d'informations sur OFFSET

0

Dans SQL il n'y a pas de mot-clé LIMIT existe.Si vous avez seulement besoin d'un nombre limité de lignes, vous devez utiliser un mot-clé TOP qui est similaire à une LIMIT.

Questions connexes