Làm cách nào để viết LINQ's .Skip (1000) .Take (100) trong SQL thuần túy?


93

.Skip()Phương thức trong LINQ tương đương với SQL là gì?

Ví dụ: Tôi muốn chọn hàng 1000-1100 từ một bảng cơ sở dữ liệu cụ thể.

Điều này có thể thực hiện được chỉ với SQL không? Hay tôi cần chọn toàn bộ bảng, sau đó tìm các hàng trong bộ nhớ? Lý tưởng nhất là tôi muốn tránh điều này, nếu có thể, vì chiếc bàn có thể khá lớn.

Câu trả lời:


78

Trong SQL Server 2005 trở lên, bạn có thể sử dụng hàm ROW_NUMBER . ví dụ.

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 51 AND 60; --BETWEEN is inclusive

Xem liên kết trong câu trả lời của tôi để biết thêm một chút chi tiết. stackoverflow.com/questions/1744802/…
Mike Atlas

GIỮA 51 và 60 - nó bao gồm.
Drew Miller

1
Nhưng điều này đầu tiên sẽ chọn tất cả và sau đó từ lựa chọn đó chỉ lấy 10 phải không? Hay truy vấn / chế độ xem đầu tiên sẽ chỉ có 10?
Tadej

138

SQL Server 2012 trở lên đã thêm cú pháp này:

SELECT *
FROM Sales.SalesOrderHeader 
ORDER BY OrderDate
OFFSET (@Skip) ROWS FETCH NEXT (@Take) ROWS ONLY

11
Lưu ý rằng bạn cần sử dụng ORDER BY ___ để sử dụng lệnh OFFSET .... không phải là bạn nên thử phân trang mà không có lệnh.
James Haug

Cũng lưu ý rằng cú pháp 'mới' có một tuyến tính hình phạt hiệu suất với @skip! Phương pháp row_number KHÔNG có điều này (chỉ được thử nghiệm trên thứ tự được lập chỉ mục). Đối với lo @Skip nhỏ hơn khoảng 20, cú pháp mới nhanh hơn so với cách tiếp cận row_number.
Eske Rahn

22

LINQ to SQL thực hiện điều này bằng cách sử dụng hàm cửa sổ ROW_NUMBER:

  SELECT a,b,c FROM 
   (SELECT a,b,c, ROW_NUMBER() OVER (ORDER BY ...) as row_number
    FROM Table) t0
   WHERE to.row_number BETWEEN 1000 and 1100;

Điều này hoạt động, nhưng nhu cầu tạo ra row_number từ ORDER BY có thể dẫn đến việc truy vấn của bạn được sắp xếp ở phía máy chủ và gây ra sự cố về hiệu suất. Ngay cả khi một chỉ mục có thể đáp ứng yêu cầu ORDER BY, truy vấn vẫn phải đếm 1000 hàng trước khi bắt đầu trả về kết quả. Tất cả các nhà phát triển thường quên điều này và chỉ ném kiểm soát phân trang trên bảng 5 triệu hàng và tự hỏi tại sao trang đầu tiên được trả lại nhanh hơn trang cuối cùng ...

Không hơn không kém, sử dụng ROW_NUMBER () có lẽ là sự cân bằng tốt nhất giữa tính dễ sử dụng và hiệu suất tốt, miễn là bạn đảm bảo tránh sắp xếp (điều kiện ORDER BY có thể được đáp ứng bởi một chỉ mục).


1
Cảm ơn về thông tin hiệu suất bổ sung, sẽ phải cẩn thận và kiểm tra nó.
Ray

Đã kiểm tra và đối với bảng nửa triệu hàng của tôi, trang cuối cùng đó chậm hơn trang đầu tiên khoảng 7 lần. Không lý tưởng, nhưng có thể chấp nhận được đối với tôi.
Ray

6

Hãy thử cái này:

select * from [Table-Name] order by [Column-Name] 
offset [Skip-Count] rows
FETCH NEXT [Take-Count] rows only

Thí dụ:

select * from Personals order by Id
offset 10 rows            --------->Skip 10
FETCH NEXT 15 rows only   --------->Take 15

4

Làm cái này:

Chạy .Skip (1000) .Take (100) trên văn bản dữ liệu LINQ to SQL và xem đầu ra SQL. Nó sẽ tạo cho bạn một câu lệnh SQL thực hiện những gì bạn đang mô tả.

Nó sẽ không thanh lịch nhưng nó sẽ hoàn thành công việc.


2
Không phải những gì đang được hỏi.
RayLoveless

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.