0

次のエンティティを持つモデルがあります。

Game: Id
User: Id
UserRating: Id, UserId, GameId, Value

ユーザーはゲームに評価を付けることができます。

レーティングが最も高い上位 5 つのゲームを返すクエリが必要です。最高のレーティングはバリューに基づいている必要がありますが、同じレーティングのゲームが 2 つ以上ある場合は、その数も考慮する必要があります。

ラムダ式を使用して、これをクエリで表現し、結果リストを Game エンティティとして返すにはどうすればよいですか?

(EF 4、MVC、SQL Server を使用)。

4

1 に答える 1

2

「最高の評価」とは、「最高の平均評価」を意味すると思いますか? 次のようなものが必要なようです。

var query = from rating in db.UserRating
            group rating by rating.GameId into ratings
            orderby ratings.Average(x => x.Value) descending,
                    ratings.Count() descending
            join game in db.Game on ratings.Key equals game.Id
            select game;

var top5Games = query.Take(5);

編集:クエリ式以外の形式では、これはより苦痛になりますが、それでも実行可能です:

var top5Games = db.UserRating
                  .GroupBy(rating => rating.GameId)
                  .OrderByDescending(ratings => ratings.Average(x => x.Value))
                  .ThenByDescending(ratings => ratings.Count())
                  .Join(db.Game, r => r.Key, g => g.Id, (r, g) => g)
                  .Take(5);

この場合、ラムダ構文でそれを行うことはそれほど悪くはありません。結合からゲームを取得するだけなので...しかし、より一般的には、より厄介になります。両方の形式を理解して使用する価値はありますが、目前のクエリに対してどちらがより単純なアプローチであるかに応じて異なります。特に、複数の結合を開始すると、ラムダ構文では恐ろしいものになります。

これはそのゲームの評価を与えないことに注意してください...それを取得するには、おそらく次のようなものが必要になるでしょう:

select new { Game = game,
             RatingAverage = ratings.Average(x => x.Value),
             RatingCount = ratings.Count() }

だけではなく、クエリの最後にselect game.

また、現時点で十分なレーティングが得られていないゲームを除外することもできます。そうしないと、レーティングが 1 つでも「完璧」なゲームが常に上位に表示されます。

編集: さて、「ゲームの名前」の最後のタイブレークで、私は間違いなくクエリ式の形式を使用します:

var query = from rating in db.UserRating
            join game in db.Game on ratings.Key equals game.Id
            select new { rating, game } into pair
            group pair by pair.game into pairs
            orderby pairs.Average(x => x.rating.Value) descending,
                    pairs.Count() descending,
                    pairs.Key.Name
            select pairs.Key;

var top5Games = query.Take(5);
于 2013-03-28T11:14:54.180 に答える