2011-11-12 14 views
4

私は自分の評価に基づいて写真のリストを並べ替えるコードを書いています。各写真はDBに格納されており、それぞれ正および負の投票数などの情報を持っています。私は正の票の割合を数える式で注文したいと思います。最初の写真は最高の割合です。私自身のOrderBy関数

私は標準のIComparerインターフェイスを使用し、2つの写真を比較する独自のComparer関数を書きました。問題は、まずデータベースからすべての写真のリストをダウンロードする必要があるということです。私が避けたいと思う多くの不必要な努力のようです。だからDB側で比較を行う自分のSQL関数を作成することが可能かどうか疑問に思っています。サーバー側のすべての写真を比較するより効率的ですか?

自分自身の比較演算のためのコード:

public class PictureComparer : IComparer<Picture> 
{ 
    public int Compare(Picture p1, Picture p2) 
    { 
     double firstPictureScore = (((double)p1.PositiveVotes/(double)(p1.PositiveVotes+p1.NegativeVotes))*100); 
     double secondPictureScore = (((double)p2.PositiveVotes/(double)(p2.PositiveVotes + p2.NegativeVotes)) * 100); 
     if (firstPictureScore < secondPictureScore) return 1; 
     if (firstPictureScore > secondPictureScore) return -1; 
     return 0; 
    } 
} 

そしてcomaprerを使用するコード:

var pictures = db.Pictures.Include(q => q.Tags).Include(q => q.User).ToList(); 
pictures = pictures.OrderBy(q => q, new PictureComparer()).Skip(0 * 10).Take(10).ToList(); 
+0

あなたの質問への答えを考えた直前に、PictureComparer.Compare()メソッドでは、firstPictureScoreとsecondPictureScoreを計算するときに* 100を忘れることがあります。比較で何も変更されません – PierrOz

+0

必要なレコードのみを返し、EFから呼び出すストアドプロシージャをコード化することができない理由は何ですか? – Oded

+0

あなたは「私が欲しい写真」とはどういう意味ですか?最初のXのもの? – PierrOz

答えて

6

ToListへの最初の呼び出しを削除し、比較演算子を定義するのではなく、ラムダ式を使用します。

var result = db.Pictures 
    .Include(q => q.Tags) 
    .Include(q => q.User) 
    .OrderByDescending(q => 
     q.PositiveVotes + q.NegativeVotes == 0 
      ? -1 
      : q.PositiveVotes/(double)(q.PositiveVotes + q.NegativeVotes)) 
    .Skip(n * 10) 
    .Take(10) 
    .ToList(); 
+0

うわー、それは速かった。それは素晴らしいコードのように見えます、そして、私が理解するところでは、並べ替えはDB側で行われますか?しかし、私はそのコードに1つの問題があります。私は正または負の投票数が0の要素を除外したくないので、リストの最後にそれらを入れたいのですか? – domderen

+0

@Tromax:私の更新答えを見てください。 –

+0

うわー、あなたは最高です!、ありがとう、魅力のような作品:) – domderen

1

あなた比較演算コードでの計算は、(i独立しています。 e。比較は単に、比較している項目を参照せずに計算できる値の順序に依存します)。したがって、最初に正のパーセンテージの数値を計算して、コンパーマで計算された値を使用するだけです。

これは可能であればデータベース内で実行する必要があります(データベースにアクセスするためのアクセス権がある場合など)。データベースはこの種の計算に適しており、計算された値をキャッシュすることなく、即座に実行することができます。計算された値を事前計算して保存するのではなく、正または負の投票。これにより、比較するすべての写真をダウンロードする必要がなくなります。正のパーセンテージで注文することができます。以下は、仕事を行うサンプルSQLです(ほんのサンプルであることに注意してください...投票をもっと効率的に保存したいかもしれません)。投票テーブルには、特定の画像の投票のリストと投票した人のリストが含まれています。

declare @votes table(
pictureId int, 
voterId int, 
vote int) 

insert into @votes select 1,1,1 
insert into @votes select 1,2,-1 
insert into @votes select 1,3,1 
insert into @votes select 1,4,1 
insert into @votes select 2,1,-1 
insert into @votes select 2,2,-1 
insert into @votes select 2,3,1 
insert into @votes select 2,4,1 

declare @votesView table(
pictureId int, 
positiveVotes int, 
NegativeVotes int) 

insert into @votesView 
select pictureId, sum(case when vote > 0 then 1 else 0 end) as PositiveVotes, 
SUM(case when vote < 0 then 1 else 0 end) as NegativeVotes from @votes group by pictureId 

select pictureId, convert(decimal(6,2),positiveVotes)/convert(decimal(6,2), (positiveVotes + negativeVotes)) as rating from @votesView 
+0

いいえ、私が理解する限り、常に「ポジティブパーセンテージ」の値を保存し、新しい投票を追加する時点で計算する方が良いでしょうか? – domderen

+1

それは一方的な方法ですが、おそらく必須ではありません。ちょうど計算を維持するビューがあります。最も簡単な方法は、2つのビューを作成することです。最初は正と負の投票を合計し(2番目の最後のselectステートメントは上記のコードを参照)、2番目のビューはこのビューを参照し、上記の最後の選択ステートメント)。ビューが常に最新であるため、誰かが投票したときに何もする必要はありません。 –

関連する問題