Как реализовать LIMIT с Microsoft SQL Server?
-
03-07-2019 - |
Вопрос
У меня есть этот запрос с MySQL:
select * from table1 LIMIT 10,20
Как я могу сделать это с помощью Microsoft sql?
Решение
Начиная с 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 предложения LIMIT является преступлением.Вам не придется делать такой неуклюжий обходной путь.
Начиная с 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, возвращаемый набор результатов не соответствует ожиданиям.
Это почти дубликат вопроса, который я задал в октябре:Эмуляция предложения 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's отвечать.
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
ПРИМЕЧАНИЕ: OFFSET
может использоваться только с или в тандеме с ORDER BY
.
Чтобы объяснить строку кода OFFSET xx ROWS FETCH NEXT yy ROW ONLY
А xx
— это номер записи/строки, с которой вы хотите начать извлечение в таблице, т.е.:Если в таблице 1 40 записей, приведенный выше код начнет получать данные со строки 10.
А yy
— это количество записей/строк, которые вы хотите извлечь из таблицы.
Чтобы использовать предыдущий пример:Если в таблице 1 40 записей, и вы начали извлекать данные из строки 10 и получить СЛЕДУЮЩИЙ набор из 10 (yy
).Это будет означать, что приведенный выше код будет извлекать записи из таблицы 1, начиная с строки 10 и заканчивая строкой 20.Таким образом протягиваем 10 – 20 ряды.
Перейдите по ссылке для получения дополнительной информации о КОМПЕНСИРОВАТЬ
Синтаксически запрос 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
Это одна из причин, по которой я стараюсь избегать использования 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 исправлен.Поэтому, если вам нужен другой порядок, вам придется создать другое представление.
ОБНОВЛЯТЬ
Есть еще одна проблема с этим подходом:если вы попытаетесь отфильтровать свои данные, это не будет работать должным образом.Например, если вы делаете:
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.
Должен попробовать.В приведенном ниже запросе вы можете увидеть группировку, упорядочение, пропуск строк и ограничение строк.
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
Если ваш идентификатор является уникальным типом идентификатора или ваш идентификатор в таблице не отсортирован, вы должны сделать следующее.
select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5
Код будет
select * from limit 2,5
Если я правильно помню (прошло много времени с тех пор, как я занимался 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. Приятно читать, особенно комментарии.