1

ユーザーのデータテーブルとuser_ratingsの別のテーブルがあります。これは1対多の関係であるため、それらはによって結合されUserIdます。usersテーブルが主キーであり、user_ratingsが外部キーの関係にあります。各user_ratingsには、rating_valueという列があり、その列はint、負、または正で埋められ、合計されてユーザーの評価として計算されます。特定の評価の日付に応じて、各ユーザーの評価を取得できるようにしたいと思います。これが私のlinqステートメントでこれまでに持っているものですが、それは正しくないと思います。

var profiles = from userprofs in Ent.UserProfiles
               join userratings in Ent.UserRatings on userprofs.UserId equals userratings.UserId
               where userratings.DateAdded >= drm.Start
               group userprofs by userprofs.UserId into g
               select new { ... };

ここからどこに行けばいいのかわからないので、グループを正しく使っているかどうかわかりません。後でこのコレクションを繰り返し処理して、user_ratingsの合計に基づいて各ユーザーとそれに関連する評価を表示できるようにしたいと思います。

4

2 に答える 2

3

評価について知りたいすべての情報が集計情報(合計、平均、カウントなど)である場合は、次のようなことを行うことができます。

var profiles = from userprof in Ent.UserProfiles
  join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
  where userrating.DateAdded >= drm.Start
  group userrating by userprof into g
  select new {g.Key.UserID, g.Key.UserName, Count = g.Count(), Avg = g.Avg(r => r.RatingValue) };

個々のアイテムに関してlinqクエリを定義するため、複数形を単数形に変更したことに注意してください(UserProfilesは複数形であり、userprofは各アイテムの「中」にあります)。

これには、SQLへの簡単な変換があります。

SELECT up.userID, up.userName, COUNT(ur.*), AVG(ur.ratingValue)
FROM UserProfiles up JOIN UserRatings ur
ON up.userID = ur.userID
WHERE dateAdded > {whatever drm.Start is}
GROUP BY up.userID, up.userName

個々の評価を取得できるようにしたい場合、これは単一のSQLクエリとあまり一致しません。次のようにすることができます。

var profiles = from userprof in Ent.UserProfiles
  join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
  where userrating.DateAdded >= drm.Start
  group new{userrating.RatingValue, userrating.SomeThing} by new{userprof.UserID, userprof.UserName};

これIEnumerable<Grouping<{anonymous object}, {anonymous object}>>により、反復して新しい反復を取得し、それKey.UserIDKey.UserName反復して次のように反復できるようにitem.RatingValueなりますitem.SomeThing(デモンストレーション用に追加しました。値だけが必要な場合は、次のようになりますIEnumerable<Grouping<{anonymous object}, int>>) 。これ:

foreach(var group in profiles)
{
  Console.WriteLine("The user is :" + group.Key.UserName + " (id: " + group.Key.UserID ")");
  foreach(var item in group)
  {
    Console.WriteLine(item.SomeThing + " was rated " + item.RatingValue);
  }
}

ただし、これに伴う問題は、これがマップされる優れた単一のSQLクエリがないことです。Linqは最善を尽くしますが、それはいくつかのクエリを実行することを意味するので、それを手伝うほうがよいでしょう:

var profiles = from item in (from userprof in Ent.UserProfiles
  join userrating in Ent.UserRatings on userprofs.UserId equals userratings.UserId
  where userrating.DateAdded >= drm.Start
  select new{userrating.RatingValue, userrating.SomeThing, userprof.UserID, userprof.UserName}).AsEnumerable()
  group new{item.RatingValue, item.SomeThing} by new{item.UserID, item.UserName}

これは以前と同じ出力ですが、SQLに変換すると、単一のクエリを実行でき、残りの作業はメモリ内で実行されます。99%の場合、このように一部の作業をメモリにドラッグすると効率が低下しますが、前のクエリにはマップできるSQLクエリが1つもないため、例外です。

于 2012-08-26T21:26:03.997 に答える
0

私があなたの質問を理解した場合:

from userprofs in Ent.UserProfiles
join userratings in Ent.UserRatings on userprofs.UserId equals userratings.UserId
where userratings.DateAdded >= drm.Start
group new{userprofs,userratings} by userprofs.UserId into g
select new { userId=g.Key, userRating=g.Sum(i=>i.userratings.rating_value) };

GroupByIEnumerableのを返しますIGrouping。AnIGroupingは基本的に、グループ化に使用されたプロパティを含むIEnumerable追加のプロパティを持つです。KeyあなたSumrating_valueグループ化の場合、あなたはそこにいます。

于 2012-08-26T20:18:18.310 に答える