Как реализовать LIMIT с Microsoft SQL Server?

У меня есть этот запрос с mysql:

select * from table1 LIMIT 10,20

Как я могу сделать это с Microsoft sql ?

14 ответов


запуск SQL SERVER 2005, вы можете сделать это...

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;

или что-то вроде этого для 2000 и ниже версий...

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

неуклюжий, но это сработает.

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

упущение MSSQL предельного положения является преступным, IMO. Вы не должны делать такого рода обходной путь.


начиная с SQL SERVER 2012, можно использовать предложение 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

Это может работать неправильно, если ордер by не уникален.

если запрос изменен на ORDER BY OrderDate, результирующий набор возвращается не так, как ожидалось.


Это почти дубликат вопроса, который я задал в октябре: эмулировать предложение MySQL LIMIT в Microsoft SQL Server 2000

если вы используете Microsoft SQL Server 2000, нет хорошего решения. Большинству людей приходится прибегать к захвату результата запроса во временной таблице с помощью IDENTITY первичный ключ. Затем запросите столбец первичного ключа с помощью BETWEEN состояние.

если вы используете Microsoft SQL Server 2005 или более поздней версии, у вас есть ROW_NUMBER() функция, поэтому вы можете получить тот же результат, но избежать временной таблицы.

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;

вы также можете написать это как общее табличное выражение как показано в @Леон Тайсон это ответ.


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

вот как я ограничиваю результаты в MS SQL Server 2012

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

Примечание: смещение можно использовать только с или в тандеме для заказа.

чтобы объяснить смещение строки кода xx строк, извлеките следующую строку yy только

" xx " - это номер записи / строки, который вы хотите начать вытягивать из таблицы.
IE: если есть запись 40 в таблице 1. Код выше начнет вытягивать из строки 10.

"yy" - это количество записей / строк, которые вы хотите вытащить со стола.
для построения на предыдущем примере.
IE: если таблица 1 имеет 40 записей, и вы начали вытягивать из строки 10 и захватить следующий набор 10 (yy).
это означало бы, что приведенный выше код вытащит записи из таблицы 1, начиная с строки 10 и заканчивая 20. Таким образом, потянув строк 10 - 20.

Проверьте ссылку для получения дополнительной информации о смещение


синтаксически MySQL LIMIT query-это что-то вроде этого:

SELECT * FROM table LIMIT OFFSET, ROW_COUNT

Это можно перевести в Microsoft SQL Server, как

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

теперь ваш запрос select * from table1 LIMIT 10,20 будет такой:

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

Это одна из причин, по которой я стараюсь избегать использования MS Server... но все равно. Иногда у вас просто нет выбора (yei! и я должен использовать устаревшую версию!!).

мое предложение-создать виртуальную таблицу:

From:

SELECT * FROM table

в:

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

потом просто запрос:

SELECT * FROM v_table WHERE row BETWEEN 10 AND 20

если поля добавлены или удалены, "строка" обновляется автоматически.

основная проблема с этой опцией заключается в том, что ORDER BY зафиксированный. Поэтому, если вы хотите другой порядок, вам придется создать другое представление.

обновление

есть еще одна проблема с этим подходом: если вы попытаетесь отфильтровать данные, он не будет работать как ожидалось. Например, если вы делаете:

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

WHERE ограничивается теми данными, которые находятся в строках между 10 и 20 (вместо поиска всего набора данных и ограничения вывода).


это многоэтапный подход, который будет работать в 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

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;

в SQL нет ключевого слова LIMIT. Если вам нужно только ограниченное количество строк, вы должны использовать ключевое слово TOP, похожее на LIMIT.


надо попробовать. В приведенном ниже запросе вы можете увидеть group by, order by, Skip rows и limit rows.

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

Если я правильно помню (прошло некоторое время с тех пор, как я пробовал SQL Server), вы можете использовать что-то вроде этого: (2005 и выше)

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

SELECT TOP 10 * FROM table;

это то же самое, что

SELECT * FROM table LIMIT 0,10;

вот статья о реализации Limit в MsSQL его приятно читать, особенно комментарии.