LIMIT 10..20 в SQL Server - PullRequest
       72

LIMIT 10..20 в SQL Server

154 голосов
/ 09 июня 2009

Я пытаюсь сделать что-то вроде:

SELECT * FROM table LIMIT 10,20

или

SELECT * FROM table LIMIT 10 OFFSET 10

, но с использованием SQL Server

Единственное найденное мной решение выглядит как излишнее:

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE row > 5 and row <= 10

Я также нашел :

SELECT TOP 10 * FROM stuff; 

... но я не хочу этого делать, поскольку не могу указать начальный лимит.

Есть ли другой способ для меня это сделать?

Также, просто любопытно, есть ли причина, почему SQL Server не поддерживает функцию LIMIT или что-то подобное? Я не хочу быть злым, но это действительно похоже на то, что нужно СУБД. Последние 5 лет я работаю с MySQL и SQL +, поэтому ...

Ответы [ 15 ]

122 голосов
/ 11 февраля 2012

Для SQL Server 2012 + вы можете использовать .

SELECT  *
FROM     sys.databases
ORDER BY name 
OFFSET  5 ROWS 
FETCH NEXT 5 ROWS ONLY 
100 голосов
/ 09 июня 2009

Предложение LIMIT не является частью стандартного SQL. Он поддерживается как расширение вендора для SQL MySQL, PostgreSQL и SQLite.

База данных других марок может иметь аналогичные функции (например, TOP в Microsoft SQL Server), но они не всегда работают одинаково.

Трудно использовать TOP в Microsoft SQL Server для имитации предложения LIMIT. Есть случаи, когда это просто не работает.

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

Другое решение заключается в использовании TOP для извлечения первых count + смещений строк, а затем с помощью API для поиска после первых смещений строк .

Смотри также:

34 голосов
/ 09 июня 2009

Как вы обнаружили, это предпочтительный метод сервера sql:

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE a.row > 5 and a.row <= 10
10 голосов
/ 04 июля 2012

Если вы используете SQL Server 2012+, проголосуйте за ответ Мартина Смита и используйте расширения OFFSET и FETCH NEXT до ORDER BY,

Если вам не повезло застрять в более ранней версии, вы можете сделать что-то вроде этого,

WITH Rows AS
(
    SELECT
              ROW_NUMBER() OVER (ORDER BY [dbo].[SomeColumn]) [Row]
            , *
        FROM
              [dbo].[SomeTable]
)
SELECT TOP 10
          *
     FROM
         Rows
    WHERE Row > 10

Я считаю, что функционально эквивалентно

SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn

и лучший из известных мне способов сделать это в TSQL до MS SQL 2012.


Если строк очень много, вы можете получить более высокую производительность, используя временную таблицу вместо CTE.

7 голосов
/ 09 июня 2009

К сожалению, ROW_NUMBER() - лучшее, что вы можете сделать. Это на самом деле более правильно, потому что результаты предложения limit или top на самом деле не имеют значения без учета какого-то определенного порядка. Но все равно это боль.

Обновление: Sql Server 2012 добавляет limit -подобную функцию через OFFSET и FETCH ключевые слова . Это нестандартный подход, в отличие от LIMIT, который является нестандартным расширением MySql.

5 голосов
/ 09 июня 2009

Как насчет этого?

SET ROWCOUNT 10 

SELECT TOP 20 *
FROM sys.databases
ORDER BY database_id DESC

Это дает вам последние 10 строк из первых 20 строк. Недостатком является то, что порядок обратный, но, по крайней мере, его легко запомнить.

2 голосов
/ 10 января 2011
SELECT TOP 10 *
FROM TABLE
WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE)

Должны дать записи 11-20. Вероятно, не слишком эффективен при увеличении, чтобы получить дополнительные страницы, и не уверен, как это может повлиять на порядок. Может потребоваться указать это в обоих операторах WHERE.

1 голос
/ 12 апреля 2016

Эквивалентом LIMIT является SET ROWCOUNT, но если вам нужна общая нумерация страниц, лучше написать запрос, подобный этому:

;WITH Results_CTE AS
(
    SELECT
        Col1, Col2, ...,
        ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
    FROM Table
    WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= @Offset
AND RowNum < @Offset + @Limit
1 голос
/ 01 марта 2016

Только для рекордного решения, которое работает на большинстве систем баз данных, но, возможно, не является самым эффективным:

Select Top (ReturnCount) *
From (
    Select Top (SkipCount + ReturnCount) *
    From SourceTable
    Order By ReverseSortCondition
) ReverseSorted
Order By SortCondition

Примечание Pelase: последняя страница будет по-прежнему содержать строки ReturnCount, независимо от того, что такое SkipCount. Но это может быть хорошо во многих случаях.

1 голос
/ 28 ноября 2013

Хороший способ - создать процедуру:

create proc pagination (@startfrom int ,@endto int) as
SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name desc) as row FROM sys.databases 
 ) a WHERE a.row > @startfrom and a.row <= @endto

просто как предел 0,2 /////////////// выполнить нумерацию страниц 0,4

...