Как реализовать LIMIT с Microsoft SQL Server? - PullRequest
112 голосов
/ 02 марта 2009

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

select * from table1 LIMIT 10,20

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

Ответы [ 15 ]

111 голосов
/ 02 марта 2009

Начиная с 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
51 голосов
/ 02 марта 2009

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

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

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

26 голосов
/ 16 сентября 2014

Начиная с 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

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

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

18 голосов
/ 02 марта 2009

Это почти копия вопроса, который я задал в октябре: Эмулировать предложение 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;

Вы также можете написать это как общее табличное выражение , как показано в ответе @Leon Tayson .

12 голосов
/ 19 мая 2016

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

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

ПРИМЕЧАНИЕ. OFFSET можно использовать только вместе с ORDER BY. Или вместе с ним.

Чтобы объяснить строку кода OFFSET xx ROWS FETCH NEXT yy ТОЛЬКО ROW

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

"yy" - это количество записей / строк, которые вы хотите извлечь из таблицы.
Для построения на предыдущем примере.
IE: если в таблице 1 имеется 40 записей, и вы начали вытягивать из строки 10 и захватить СЛЕДУЮЩИЙ набор 10 (гг).
Это означает, что приведенный выше код будет извлекать записи из таблицы 1, начиная со строки 10 и заканчивая 20. Таким образом, вытягивая строки 10 - 20.

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

12 голосов
/ 02 марта 2009
SELECT  *
FROM    (
        SELECT  TOP 20
                t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
        FROM    table1 t
        ORDER BY
                field1
        ) t
WHERE   rn > 10
8 голосов
/ 06 марта 2012

Синтаксически запрос MySQL LIMIT выглядит примерно так:

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 
2 голосов
/ 17 апреля 2014

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

Я предлагаю создать виртуальную таблицу:

От:

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 исправлен. Поэтому, если вы хотите другой порядок, вам придется создать другой вид.

UPDATE

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

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

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

1 голос
/ 28 февраля 2013
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 голос
/ 02 марта 2009

Это многошаговый подход, который будет работать в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...