如何使用Microsoft SQL Server实施LIMIT?

How to implement LIMIT with Microsoft SQL Server?

我有这个查询与mysql:

1
SELECT * FROM table1 LIMIT 10,20

如何使用Microsoft sql执行此操作?


启动SQL SERVER 2005,可以执行此操作...

1
2
3
4
5
6
7
8
9
10
11
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及以下版本...

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


笨拙,但可以使用。

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

IMO忽略了MSSQL的LIMIT子句。您不必执行这种笨拙的解决方法。


从SQL SERVER 2012开始,可以使用OFFSET FETCH子句:

1
2
3
4
5
6
7
8
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/zh-CN/library/ms188385(v=sql.110).aspx

如果订购依据不是唯一的,这可能无法正常工作。

如果查询被修改为ORDER BY OrderDate,则返回的结果集与预期的不同。


这几乎是我十月份提出的一个问题的重复:
在Microsoft SQL Server 2000中模拟MySQL LIMIT子句

如果您使用的是Microsoft SQL Server 2000,则没有好的解决方案。大多数人不得不诉诸使用IDENTITY主键在临时表中捕获查询结果。然后使用BETWEEN条件查询主键列。

如果使用的是Microsoft SQL Server 2005或更高版本,则具有ROW_NUMBER()函数,因此可以获得相同的结果,但要避免使用临时表。

1
2
3
4
5
6
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的答案所示。


这就是我如何限制MS SQL Server 2012中的结果:

1
2
3
4
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行开始提取并获取NEXT集10(yy)。
这意味着,上面的代码将从表1中的记录开始,从第10行开始,到第20行结束。因此,提取第10-20行。

查看链接以获取有关OFFSET的更多信息


1
2
3
4
5
6
7
8
9
SELECT  *
FROM    (
        SELECT  TOP 20
                t.*, ROW_NUMBER() OVER (ORDER BY field1) AS rn
        FROM    table1 t
        ORDER BY
                field1
        ) t
WHERE   rn > 10


从语法上来说,MySQL LIMIT查询是这样的:

1
SELECT * FROM TABLE LIMIT OFFSET, ROW_COUNT

可以将其翻译成Microsoft SQL Server,例如

1
2
3
4
5
6
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将如下所示:

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

这是我尝试避免使用MS Server的原因之一...但无论如何。有时您只是没有选择(是!我必须使用过时的版本!)。

我的建议是创建一个虚拟表:

从:

1
SELECT * FROM TABLE

至:

1
2
CREATE VIEW v_table AS    
    SELECT ROW_NUMBER() OVER (ORDER BY table_key) AS ROW,* FROM TABLE

然后只需查询:

1
SELECT * FROM v_table WHERE ROW BETWEEN 10 AND 20

如果添加或删除字段,"行"将自动更新。

此选项的主要问题是ORDER BY是固定的。因此,如果您想要不同的顺序,则必须创建另一个视图。

更新

这种方法还有另一个问题:如果尝试过滤数据,它将无法按预期工作。例如,如果您这样做:

1
SELECT * FROM v_table WHERE FIELD = 'test' AND ROW BETWEEN 10 AND 20

WHERE限制为位于10到20之间的行中的那些数据(而不是搜索整个数据集并限制输出)。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
2
3
4
5
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

这是一种多步骤方法,将在SQL2000中起作用。

1
2
3
4
5
6
-- 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


better use this in MSSQLExpress 2017.

1
2
3
4
5
SELECT * FROM
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS [COUNT], * FROM table1
) AS a
WHERE [COUNT] BETWEEN 10 AND 20;

-赋予列[Count]并为每一行分配唯一的计数而无需排序,然后再次选择可以提供限制的位置。::)


在SQL中,不存在LIMIT关键字。如果只需要有限的行数,则应使用类似于LIMIT的TOP关键字。


如果您的ID是唯一标识符类型,或者表中的ID未排序,则必须在下面进行操作。

1
2
3
SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS RowNumber,* FROM table1) a
WHERE a.RowNumber BETWEEN 2 AND 5

该代码将是

1
SELECT * FROM LIMIT 2,5

如果我没记错(自从使用SQL Server以来已经有一段时间了),您也许可以使用类似这样的命令:(2005年及以上)

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


1
SELECT TOP 10 * FROM TABLE;

是相同的

1
SELECT * FROM TABLE LIMIT 0,10;

这是一篇有关在MsSQL中实现Limit的文章。它是一本不错的书,特别是注释。