2010-11-17 44 views
15

Bất kỳ ai biết cách viết một câu lệnh LINQ to SQL để trả về mọi hàng thứ n từ một bảng? Tôi cần lấy tiêu đề của mục ở đầu mỗi trang trong lưới dữ liệu được phân trang lại để quét nhanh người dùng. Vì vậy, nếu tôi muốn kỷ lục đầu tiên, sau đó mỗi người thứ 3 sau đó, từ những tên sau đây:LINQ to SQL Mỗi hàng thứ N từ bảng

Amy, Eric, Jason, Joe, John, Josh, Maribel, Paul, Steve, Tom

Tôi sẽ nhận được Amy, Joe, Maribel và Tom.

Tôi nghi ngờ điều này có thể được thực hiện ... Các câu lệnh LINQ to SQL đã gọi hàm SQL ROW_NUMBER() cùng với phân loại và phân trang. Tôi chỉ không biết cách lấy lại mọi thứ thứ n. Câu lệnh SQL sẽ có dạng như WHERE ROW_NUMBER MOD 3 = 0, nhưng tôi không biết câu lệnh LINQ để sử dụng để lấy đúng SQL.

+0

Tôi không biết nếu điều này có thể được thực hiện với LINQ to SQL tạo sql – hunter

+0

Có thực sự (Không, REALLY) dường như không phải là một cách để đi đến giải pháp cơ bản của câu trả lời được chấp nhận bằng cách sử dụng LINQ to SQL tinh khiết. Tôi đã sử dụng một vài lựa chọn thay thế. 1) Tạo chế độ xem mô tả bảng gốc cộng với số hàng bằng cách sử dụng sắp xếp mong muốn, sau đó sử dụng LINQ to SQL để truy vấn chế độ xem nơi số hàng là số không cho n trong "lấy mọi hàng n". 2) Sử dụng câu trả lời được chấp nhận và ExecuteQuery. Tôi thích giải pháp đầu tiên nếu tôi biết loại mod trước phải luôn giống nhau. –

Trả lời

8

Đôi khi, TSQL là con đường để đi. Tôi sẽ sử dụng ExecuteQuery<T> đây:

var data = db.ExecuteQuery<SomeObjectType>(@" 
SELECT * FROM 
(SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS [__row] 
FROM [YourTable]) x WHERE (x.__row % 25) = 1"); 

Bạn cũng có thể trao đổi trên các n:

var data = db.ExecuteQuery<SomeObjectType>(@" 
DECLARE @n int = 2 
SELECT * FROM 
(SELECT *, ROW_NUMBER() OVER (ORDER BY id) AS [__row] 
FROM [YourTable]) x WHERE (x.__row % @n) = 1", n); 
1

Có thực sự dường như không thể là một cách dễ dàng để làm điều này:

How do I add ROW_NUMBER to a LINQ query or Entity?

How to find the ROW_NUMBER() of a row with Linq to SQL

Nhưng luôn có:

peopleToFilter.AsEnumerable().Where((x,i) => i % AmountToSkipBy == 0) 

LƯU Ý: này vẫn không thực thi ở phía cơ sở dữ liệu của mọi thứ!

+0

Thật không may là tình trạng quá tải của 'Where' không được hỗ trợ trong LINQ-to-SQL – Stephan

+0

Ahhh ... Thật không may là bạn đã ... – diceguyd30

+0

Thay đổi câu trả lời của tôi thành một cái gì đó hữu ích (đọc: thực sự hoạt động) – diceguyd30

1

Chỉ cần googling xung quanh một chút tôi đã không tìm thấy (hoặc có kinh nghiệm) một lựa chọn cho LINQ to SQL để trực tiếp hỗ trợ này.

Tùy chọn duy nhất tôi có thể cung cấp là bạn viết một thủ tục được lưu trữ với truy vấn SQL thích hợp được viết ra và sau đó gọi sproc qua LINQ to SQL. Không phải là giải pháp tốt nhất, đặc biệt là nếu bạn có bất kỳ loại lọc phức tạp nào đang diễn ra.

+0

Đây không phải là câu trả lời – hunter

+0

Đôi khi, như trong trường hợp này, câu trả lời duy nhất là không có câu trả lời. Không có cách nào để trực tiếp sử dụng 'ROW_NUMBER()' từ SQL, kiểu lựa chọn này có khả năng là không thể. – Stephan

+0

Tôi nghĩ rằng có một cách giống như những gì tôi đã viết, chỉ cần suy nghĩ về nó theo một cách khác. –

1

này sẽ làm các trick, nhưng nó không phải là truy vấn hiệu quả nhất trên thế giới:

var count = query.Count(); 
var pageSize = 10; 
var pageTops = query.Take(1); 
for(int i = pageSize; i < count; i += pageSize) 
{ 
    pageTops = pageTops.Concat(query.Skip(i - (i % pageSize)).Take(1)); 
} 
return pageTops; 

Nó tự động xây dựng một truy vấn để kéo (thứ n, 2 * thứ n, 3 * thứ n, vv) giá trị từ truy vấn đã cho. Nếu bạn sử dụng kỹ thuật này, có thể bạn sẽ muốn tạo giới hạn có thể là mười hoặc hai mươi tên, tương tự như cách trang kết quả của Google (1-10 và Tiếp theo), để tránh bị một biểu thức quá lớn mà cơ sở dữ liệu từ chối cố phân tích nó.

Nếu bạn cần hiệu suất tốt hơn, bạn có thể phải sử dụng thủ tục được lưu trữ hoặc dạng xem để biểu diễn truy vấn của bạn và bao gồm số hàng như một phần của kết quả proc được lưu trữ hoặc trường của chế độ xem.

3

Dưới đây là một lựa chọn mà hoạt động, nhưng nó có thể là giá trị kiểm tra rằng nó không có bất kỳ vấn đề hiệu suất trong thực tế:

var nth = 3; 
var ids = Table 
      .Select(x => x.Id) 
      .ToArray() 
      .Where((x, n) => n % nth == 0) 
      .ToArray(); 

var nthRecords = Table 
        .Where(x => ids.Contains(x.Id)); 
+2

Điều này sẽ có vấn đề khi bảng vượt quá 7000 hàng, như giới hạn thông số của máy chủ sql sẽ đạt được. –

4

Ngày xửa ngày xưa, không có những điều như ROW_NUMBER, nhưng các truy vấn như vậy là có thể. Kìa!

var query = 
    from c in db.Customers 
    let i = (
    from c2 in db.Customers 
    where c2.ID < c.ID 
    select c2).Count() 
    where i%3 == 0 
    select c; 

này tạo Sql sau

SELECT [t2].[ID], [t2]. --(more fields) 
FROM (
    SELECT [t0].[ID], [t0]. --(more fields) 
(
     SELECT COUNT(*) 
     FROM [dbo].[Customer] AS [t1] 
     WHERE [t1].[ID] < [t0].[ID] 
     ) AS [value] 
    FROM [dbo].[Customer] AS [t0] 
    ) AS [t2] 
WHERE ([t2].[value] % @p0) = @p1 
+0

mã của bạn không thể được biên dịch, tôi là gì ???? –

+0

Mã biên dịch tốt bằng C#. –

+0

Có thể trình biên dịch của bạn khác với chúng tôi ... –