2012-03-26 25 views
11

Tôi có câu lệnh SQL dưới đây hoạt động như mong muốn/mong đợi. Tuy nhiên tôi muốn dịch nó thành một câu lệnh LINQ (Lambda ??) để nó phù hợp với phần còn lại của DAL của tôi. Tuy nhiên tôi không thể nhìn thấy để tìm ra cách để mô phỏng Rank() trong LINQ.Chuyển đổi xếp hạng SQL() thành LINQ, hoặc thay thế

Lý do tôi đăng nó ở đây, có thể do lỗi, là để xem liệu có ai thay thế câu lệnh Rank() để tôi có thể chuyển đổi điều này không. Ngoài ra, nếu có một cách để đại diện cho Rank() trong LINQ cũng sẽ được đánh giá cao.

USE CMO 

SELECT  vp.[PersonID] AS [PersonId] 
      ,ce.[EnrollmentID] 
      ,vp.[FirstName] 
      ,vp.[LastName] 
      ,ce.[EnrollmentDate] 
      ,ce.[DisenrollmentDate] 
      ,wh.WorkerCategory 

FROM [dbo].[vwPersonInfo] AS vp 
      INNER JOIN 
      (
        [dbo].[tblCMOEnrollment] AS ce 
        LEFT OUTER JOIN 
         (
           SELECT * 
              ,RANK()OVER(PARTITION BY EnrollmentID ORDER BY CASE WHEN EndDate IS NULL THEN 1 ELSE 2 END, EndDate DESC, StartDate DESC) AS whrank 
           FROM [dbo].[tblWorkerHistory] 
           WHERE WorkerCategory = 2 
         ) AS wh 
           ON ce.[EnrollmentID] = wh.[EnrollmentID] AND wh.whrank = 1 
      ) 
        ON vp.[PersonID] = ce.[ClientID] 

WHERE (vp.LastName NOT IN ('Client','Orientation','Real','Training','Matrix','Second','Not')) 
AND (
      (wh.[EndDate] <= GETDATE()) 
      OR wh.WorkerCategory IS NULL 
    ) 
AND (
      (ce.[DisenrollmentDate] IS NULL) 
      OR (ce.[DisenrollmentDate] >= GetDate()) 
    ) 
+0

@closer: quá cục bộ? –

+0

Tôi đã nghĩ rằng có lẽ tôi nên làm lại điều này để chỉ đơn giản là hỏi làm thế nào để yếu tố ra các Sub-Chọn với Rank(). Điều đó có tạo ra một câu hỏi hay hơn không? –

+0

Bạn có thể sử dụng chế độ xem với mệnh đề xếp hạng - đang chờ người khác biết nếu có thể với LINQ thô. –

Trả lời

10

Dưới đây là một ví dụ cho thấy làm thế nào tôi sẽ mô phỏng Rank() trong LINQ:

var q = from s in class.student 
       orderby s.Age descending 
       select new { 
        Name = s.name, 
        Rank = (from o in class.student 
          where o.mark > s.mark 
          select o).Count() + 1 
       }; 
+1

Với tôi, điều này giống như E = mc^2 ..một giải pháp cực kỳ đơn giản cho một vấn đề tương đối phức tạp – Ody

+2

Theo như các thử nghiệm của tôi đi, có vẻ như tôi đang tạo một truy vấn riêng biệt cho mỗi kết quả trong truy vấn bên ngoài. Điều này trở nên có vấn đề với thậm chí vài nghìn kết quả và do đó phương pháp này dường như bị ràng buộc. –

+1

Tôi thích suy nghĩ của bạn về giải pháp này! Tôi chưa bao giờ nghĩ đến nó theo cách đó. Làm tốt! tôi đã kết thúc sử dụng thực hiện lamda nhưng dựa trên các khái niệm tương tự: var rankedData = data.Select (s => mới { \t \t \t \t \t \t Ranking = data.Count (x => x.Value> s .Value) +1, \t \t \t \t \t \t Tên = s.Key, \t \t \t \t \t \t Điểm = s.Value}); –

2

Nếu bạn muốn mô phỏng rank thì bạn có thể sử dụng sau đây truy vấn LINQ.

 var q = (from s in class.student 
       select new 
       { 
        Name = s.Name, 
        Rank = (from o in class.student 
          where o.Mark > s.Mark && o.studentId == s.studentId 
          select o.Mark).Distinct().Count() + 1 
       }).ToList(); 

bạn có thể sử dụng để do như:

 var q = (from s in class.student 
       orderby s.studentId 
       select new 
       { 
        Name = s.Name, 
        Rank = (from o in class.student 
          where o.Mark > s.Mark && o.studentId == s.studentId 
          select o.Mark).Distinct().Count() + 1 
       }).ToList(); 

nhưng trật tự bằng cách không quan trọng trong truy vấn này.

+0

@Refracted Paladin nếu vấn đề của bạn được giải quyết, sau đó đánh dấu là câu trả lời. –

+0

Tại sao '.Distinct()'? Định nghĩa của hàm 'RANK()' sẽ yêu cầu bạn bỏ qua điều đó. Câu trả lời của bạn khớp với đầu ra cho 'DENSE_RANK()' –

7

LINQ có xếp hạng funcionality được tích hợp sẵn, nhưng không phải trong cú pháp truy vấn. Khi sử dụng cú pháp phương pháp, hầu hết các hàm LINQ đều có hai phiên bản - một hàm bình thường và một với một thứ hạng được cung cấp.

Một ví dụ đơn giản chỉ chọn mỗi học sinh khác và sau đó thêm các chỉ số trong chuỗi dẫn đến kết quả:

var q = class.student.OrderBy(s => s.studentId).Where((s, i) => i % 2 == 0) 
.Select((s,i) => new 
{ 
    Name = s.Name, 
    Rank = i 
} 
+3

Đây có phải là điều không đúng đối với các danh sách vật chất hóa, hay nó thực sự tạo ra SQL tương ứng với thứ hạng? –

+2

Khi tôi cố gắng sử dụng điều này, tôi tiếp tục nhận được thông báo "LINQ không nhận ra phương thức ..." cho đến khi tôi xóa mệnh đề where. Nó dường như không thích 2 tham số trong ngoặc đơn. – Bpainter

+0

Đây phải là câu trả lời được chấp nhận, câu trả lời được chấp nhận là có hiệu suất khủng khiếp! –

0

Dựa trên câu trả lời từ @Totero nhưng với một thực hiện lamda. Điểm cao hơn = xếp hạng cao hơn.

var rankedData = data.Select(s => new{ 
        Ranking = data.Count(x => x.Value > s.Value)+1, 
        Name = s.Key, 
        Score = s.Value}); 

Đối với đầu vào này:

{ 100, 100, 98, 97, 97, 97, 91, 50 } 

Bạn sẽ nhận được kết quả này:

  • Điểm: Rank
  • 100: 1
  • 100: 1
  • 98: 3
  • 97: 4
  • 97: 4
  • 97: 4
  • 91: 6
  • 50: 7
Các vấn đề liên quan