Làm cách nào để triển khai LIMIT với SQL Server?


130

Tôi có truy vấn này với MySQL:

select * from table1 LIMIT 10,20

Làm thế nào tôi có thể làm điều này với SQL Server?



13
Vì câu hỏi này đã được hỏi trước, nên câu hỏi còn lại có phải là bản sao không?
Tab Alleman 17/03/2015

Câu trả lời:


127

Bắt đầu SQL SERVER 2005, bạn có thể làm điều này ...

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;

hoặc một cái gì đó như thế này cho các phiên bản 2000 và thấp hơn ...

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

6
Truy vấn thứ 2 không thành công nếu bạn có ví dụ 14 hàng trong bảng. Nó cung cấp cho bạn các hàng từ 5 đến 14, nhưng bạn muốn các hàng từ 11 đến 14. Nói chung, nó không thành công cho "trang" cuối cùng của kết quả, trừ khi tổng số hàng là bội số của kích thước "trang" đó.
Bill Karwin

147
Một điều đơn giản như vậy cần phải được làm cho rất khó khăn bởi MS một lần nữa!
Martin

Đây là những gì làm việc cho tôi trong SQL Server Management Studio 2017: SELECT * FROM [dbo] <chèn tableName đây> NƠI @@ ROWCOUNT GIỮA <chèn phút ở đây> và <chèn max đây>.
Artorias2718

Thật tuyệt vời, Nó hoạt động như sự quyến rũ trong MS SQL Server 2017 chọn Statement
PatsonLeaner

58

Clunky, nhưng nó sẽ làm việc.

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

Thiếu sót của MSSQL về một điều khoản LIMIT là hình sự, IMO. Bạn không cần phải thực hiện loại giải pháp này.


Bạn có một đề nghị khác để bỏ qua điều này?
Bigballs

Tôi đã làm rất nhiều lần trong lần cuối cùng tôi phải đối phó với MSSQL và đây là giải pháp tốt nhất tôi tìm thấy. Không dễ chịu, nhưng nó hoạt động.
ceejayoz

Giải pháp này chỉ hoạt động nếu tập kết quả bao gồm một cột là duy nhất. Đây không phải là một giải pháp chung để bắt chước GIỚI HẠN cho bất kỳ truy vấn nào.
Bill Karwin

1
Tôi đang ở trong tình trạng khó khăn tương tự ngay bây giờ ... Tuy nhiên, trong trường hợp của tôi, tôi đã hoài nghi ... Thậm chí còn tội phạm hơn khi được gọi là 'chuyên gia' dba quyết định rằng một khóa duy nhất không cần thiết trong một bảng ... BẤT CỨ bảng nào ... Đừng bao giờ đưa ra chủ đề về các khóa và ràng buộc nước ngoài!
Andrew Rollings

Vấn đề với điều này là, nó không xử lý các mệnh đề WHERE rất tốt ... Tôi sẽ thử các bảng tạm thời, vì nó không hoạt động đối với tôi.
pasty khó chịu

37

Bắt đầu với SQL SERVER 2012, bạn có thể sử dụng Điều khoản FFSCH OFFSET:

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/l Library / ms188385 (v = sql.110) .aspx

Điều này có thể không hoạt động chính xác khi thứ tự bởi không phải là duy nhất.

Nếu truy vấn được sửa đổi thành ORDER BY OrderDate, tập kết quả được trả về không như mong đợi.


Sử dụng 'với' chỉ cần một nửa thời gian để hoàn thành truy vấn - xem câu trả lời của @Leon Tayson. Tôi không biết Microsoft đã làm gì để làm cho nó chậm như vậy.
isHuman

1
Tại sao đây không phải là câu trả lời được chấp nhận? Chúng tôi đang ở trong năm 2018 vì đã khóc rất to!
Đội trưởng

1
@Skipper đúng. người được chấp nhận vẫn hoạt động. Chúng ta hãy nâng cấp cái này để phản ánh bản cập nhật.
kronn

18

Đây gần như là một bản sao của một câu hỏi tôi đã hỏi vào tháng 10: Giả lập mệnh đề LIMIT của MySQL trong Microsoft SQL Server 2000

Nếu bạn đang sử dụng Microsoft SQL Server 2000, không có giải pháp tốt. Hầu hết mọi người phải dùng đến việc nắm bắt kết quả của truy vấn trong một bảng tạm thời với IDENTITYkhóa chính. Sau đó truy vấn vào cột khóa chính bằng một BETWEENđiều kiện.

Nếu bạn đang sử dụng Microsoft SQL Server 2005 trở lên, bạn có một ROW_NUMBER()chức năng, do đó bạn có thể nhận được kết quả tương tự nhưng tránh bảng tạm thời.

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;

Bạn cũng có thể viết biểu thức này dưới dạng biểu thức bảng chung như trong câu trả lời của @Leon Tayson .


ROW_NUMBER () QUÁ (ĐẶT HÀNG B) NG) nhận được điểm vì hợp lệ trong ANSI SQL: 2003, mặc dù hỗ trợ trong các DBMS khác với SQL Server là rất đáng chú ý. Và dĩ nhiên, nó khá là rắc rối ...
bobince

@bobince: Hóa ra Oracle, Microsoft SQL Server 2005, IBM DB2 và PostgreQuery 8.4 đều có các chức năng cửa sổ hỗ trợ. Điều đó bao gồm phần lớn thị trường SQL. Hỗ trợ chỉ được chú ý nếu bạn sử dụng MySQL, SQLite hoặc phiên bản cũ của DB ở trên.
Bill Karwin

16

Đây là cách tôi giới hạn kết quả trong MS SQL Server 2012:

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

LƯU Ý: OFFSETchỉ có thể được sử dụng với hoặc song song vớiORDER BY .

Để giải thích dòng mã OFFSET xx ROWS FETCH NEXT yy ROW ONLY

Các xx bản ghi / hàng bạn muốn bắt đầu kéo từ trong bảng, nghĩa là: Nếu có 40 bản ghi trong bảng 1, mã ở trên sẽ bắt đầu kéo từ hàng 10.

Các yy là số lượng hồ sơ / hàng bạn muốn kéo từ bảng.

Để xây dựng theo ví dụ trước: Nếu bảng 1 có 40 bản ghi và bạn bắt đầu kéo từ hàng 10 và lấy bộ 10 TIẾP THEO (yy ). Điều đó có nghĩa là, mã ở trên sẽ kéo các bản ghi từ bảng 1 bắt đầu từ hàng 10 và kết thúc ở 20. Do đó kéo các hàng 10 - 20.

Kiểm tra liên kết để biết thêm thông tin về OFFSET


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

Chà, tôi vừa kiểm tra, SQL Server hóa ra đủ thông minh để dừng các điều kiện ROW_NUMBER (), nếu có một cột được lập chỉ mục trong mệnh đề ORDER BY.
Quassnoi

9

Cú pháp truy vấn giới hạn MySQL là như thế này:

SELECT * FROM table LIMIT OFFSET, ROW_COUNT

Điều này có thể được dịch sang Microsoft SQL Server như

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

Bây giờ truy vấn của bạn select * from table1 LIMIT 10,20sẽ như thế này:

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

2

Đây là một trong những lý do tôi cố gắng tránh sử dụng MS Server ... nhưng dù sao đi nữa. Đôi khi bạn không có tùy chọn (yei! Và tôi phải sử dụng phiên bản lỗi thời !!).

Đề nghị của tôi là tạo một bảng ảo:

Từ:

SELECT * FROM table

Đến:

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

Sau đó, chỉ cần truy vấn:

SELECT * FROM v_table WHERE row BETWEEN 10 AND 20

Nếu các trường được thêm hoặc xóa, "hàng" sẽ được cập nhật tự động.

Vấn đề chính với tùy chọn này là ORDER BY đã được sửa. Vì vậy, nếu bạn muốn một thứ tự khác, bạn sẽ phải tạo một chế độ xem khác.

CẬP NHẬT

Có một vấn đề khác với cách tiếp cận này: nếu bạn cố gắng lọc dữ liệu của mình, nó sẽ không hoạt động như mong đợi. Ví dụ: nếu bạn làm:

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

WHERE trở nên giới hạn đối với những dữ liệu nằm trong các hàng trong khoảng từ 10 đến 20 (thay vì tìm kiếm toàn bộ dữ liệu và giới hạn đầu ra).


1

Đây là một cách tiếp cận nhiều bước sẽ hoạt động trong 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

1
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;

Là một giải pháp tuyệt vời cho tôi.
Tyde

1

Phải thử. Trong truy vấn bên dưới, bạn có thể thấy nhóm theo, sắp xếp theo, Bỏ qua các hàng và giới hạn các hàng.

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

0
SELECT TOP 10 * FROM table;

Giống như

SELECT * FROM table LIMIT 0,10;

Đây là một bài viết về việc thực hiện Giới hạn trong MsQuery. Đây là một bài đọc hay, đặc biệt là các bình luận.


1
Cảm ơn, nhưng tôi muốn hồ sơ từ 10 đến 20, có cách nào để làm điều đó?
Bigballs

5
Câu trả lời này không trả lời cho câu hỏi gốc, nhưng thật hữu ích nếu ai đó như tôi cần biết cách lấy kết quả N đầu tiên và đến đây qua google, v.v ...
brianlmerritt

0

Trong SQL không tồn tại từ khóa LIMIT. Nếu bạn chỉ cần một số lượng hàng hạn chế, bạn nên sử dụng từ khóa TOP tương tự như GIỚI HẠN.


0

Nếu ID của bạn là loại định danh duy nhất hoặc id của bạn trong bảng không được sắp xếp, bạn phải làm như thế này dưới đây.

select * from
(select ROW_NUMBER() OVER (ORDER BY (select 0)) AS RowNumber,* from table1) a
where a.RowNumber between 2 and 5



Mã sẽ là

chọn * từ giới hạn 2,5

0

sử dụng tốt hơn điều này trong MSSQLE े 2017.

SELECT * FROM
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) as [Count], * FROM table1
) as a
WHERE [Count] BETWEEN 10 and 20;

- Tạo một cột [Đếm] và gán cho mỗi hàng một số đếm duy nhất mà không cần đặt hàng sau đó chọn lại nơi bạn có thể cung cấp giới hạn của mình .. :)


0

Một trong những cách có thể để có được kết quả như dưới đây, hy vọng điều này sẽ giúp ích.

declare @start int
declare @end int
SET @start = '5000';  -- 0 , 5000 ,
SET @end = '10000'; -- 5001, 10001
SELECT * FROM ( 
  SELECT TABLE_NAME,TABLE_TYPE, ROW_NUMBER() OVER (ORDER BY TABLE_NAME) as row FROM information_schema.tables
 ) a WHERE a.row > @start and a.row <= @end

0

Cách dễ dàng

MYSQL:

SELECT 'filds' FROM 'table' WHERE 'where' LIMIT 'offset','per_page'

MSSQL:

SELECT 'filds' FROM 'table' WHERE 'where' ORDER BY 'any' OFFSET 'offset' 
ROWS FETCH NEXT 'per_page' ROWS ONLY

ĐẶT HÀNG B isNG là bắt buộc


-2

Nếu tôi nhớ chính xác (đã được một thời gian kể từ khi tôi nhúng SQL Server), bạn có thể sử dụng một cái gì đó như thế này: (2005 trở lên)

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

SQL Server 2012: Msg 207, Cấp 16, Trạng thái 1, Dòng 5 Tên cột không hợp lệ 'RowNum'.
điện tử

âm thanh như bạn có một lỗi đánh máy trong tuyên bố của bạn ở đâu đó. RowNum là tên chúng ta gán cho biểu thức. Đăng vấn đề của bạn với nguồn và cộng đồng sẽ giúp bạn
Kris

Đây không phải là cú pháp hợp lệ. Bạn không thể tham chiếu trong WHEREmột bí danh được xác định trong cùng một SELECTmệnh đề cấp .
ypercubeᵀᴹ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.