2012-03-26 14 views
11

以下のSQL文を希望どおりに動作させることができます。しかし、私はそれをLINQステートメント(Lambda ??)に翻訳して、DALの残りの部分に収まるようにしたいと思います。しかし、LINQでRank()をシミュレートする方法を理解することはできません。SQLランク()をLINQに変換するか、代替方法

私がここに投稿したのは、おそらくエラーである理由は、誰かがRank()ステートメントへの代替を持っているかどうかを確認して、これを切り替えられるようにすることです。代わりに、Rank()をLINQで表現する方法があれば、それも理解できます。

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:あまりに局在? –

+0

私はおそらく、ランク()を持つサブ選択をどのように除外するかを尋ねるために、これを再加工する必要があると考えていました。それはより良い質問をするだろうか? –

+0

あなたは生のLinqで可能であるかどうかを知っている他の誰かを保留にして、rank句でビューを使用することができます。 –

答えて

10

ここで私はランクを(シミュレートする方法を示すサンプルは、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

私には、これはE = mc^2のように感じます。比較的複雑な問題に対する信じられないほど単純な解決策です。 – Ody

+2

私のテストでは、外側のクエリに1つの別のクエリを作成しているようです。これは数千の結果でさえ問題になるので、この方法は限定されているようです。 –

+1

私はこのソリューションのあなたの考えが好きです!私はそのように見ることは決して考えなかった。よくやった! 私はラムダ実装を使用して終了しますが、同じ考え方に基づいて: VAR rankedData = data.Select(S =>新しい{ \t \t \t \t \t \tランキング= data.Count(X => x.Value> S .VALUE)+1、 \t \t \t \t \t \t NAME = s.Key、 \t \t \t \t \t \tスコア= s.Value})。 –

2

あなたはランクをシミュレートしたい場合、あなたは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(); 

次のような順を使用することができます。

 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(); 

が、順序によっては、このクエリでは重要ではありません。

+0

あなたの問題が解決したら、答えとしてマークしてください。 –

+0

なぜ '.Distinct()'ですか? 'RANK()'関数の定義には、それを省略する必要があります。あなたの答えは 'DENSE_RANK() 'の出力と一致します –

7

LINQにはランクの機能が組み込まれていますが、クエリ構文には組み込まれていません。メソッドの構文を使用するとき、ほとんどのlinq関数には2つのバージョンがあります - 通常のものと、ランク付けされたものがあります。

結果に結果のシーケンス内のインデックスを追加するだけ他のすべての学生を選択し、簡単な例:

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

これは厳密にマテリアライズド・リストではないのですか、それとも実際にランク付けに対応するSQLを生成していますか? –

+2

これを使用しようとすると、where節を削除するまで、「LINQはメソッドを認識しません...」というメッセージが表示され続けます。括弧内の2つのパラメータが気に入らないようです。 – Bpainter

+0

これは受け入れられた答えであり、受け入れられたものはひどいパフォーマンスです! –

0

@Toteroからではなく、ラムダ実装との回答に基づいています。 高いスコア=高いランク。この入力の

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

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

あなたはこの出力を取得します:

  • スコア:ランク
  • 100:1
  • 100:1
  • 98: 3
  • 97:4
  • 97:4
  • 97:4
  • 91:6
  • 50:7