2

ミュージシャンは曲を書きます。曲は放送中に再生されます。

私はデータベーステーブルMusicians、Songs、AirTimesを持っています。AirTimesテーブルのエントリには、どの曲がどの日付で何分間再生されたかに関する情報が保持されます。

テーブルに対応するミュージシャン、ソング、エアタイムのクラスがあります。クラスには、他のエンティティを指すナビゲーションプロパティがあります。下の矢印はナビゲーションを表しています。

ミュージシャン<->歌<->AirTime

データベースから、すべてのミュージシャンと彼/彼女の曲がAirTimeを取得した日付を取得する必要があります。さらに、特定の日に再生された曲の数とその日に再生された分数を表示したいと思います。

Microsoft SQLでは、次のようにします。

select 
    dbo.Musicians.LastName
  , dbo.AirTimes.PlayDate
  , count(dbo.AirTimes.PlayDate) as 'No. of entries'
  , sum(dbo.AirTimes.Duration) as 'No. of minutes'
from dbo.Musicians
  left outer join dbo.Songs
  on dbo.Musicinas.MusicianId = dbo.Songs.MusicianId
    left outer join dbo.AirTimes
    on dbo.Songs.SongId = dbo.AirTimes.SongId
    and '2014-07-01T00:00:00' <= dbo.AirTimes.PlayDate 
    and dbo.AirTimes.PlayDate <= '2014-07-31T00:00:00'
group by 
    dbo.Musicians.LastName
  , dbo.AirTimes.PlayDate
order by
    dbo.Musicians.LastName
  , dbo.AirTimes.PlayDate

誰かがこれをlinq-to-entiteseに「翻訳」できますか?

2012年8月9日更新
grudolfのスキームが私が望んでいたことを実行していることを確認できません。私は別のテクニックで物事を成し遂げました。それにもかかわらず、私は彼/彼女の答えを受け入れます。

4

1 に答える 1

2

双方向のナビゲーション プロパティがあるため、AirTimes から開始できます。

var grpTime = (
    from a in AirTimes
    where a.Date >= firstDate && a.Date < lastDate
    group a by new {a.Song.Musician.LastName, a.Song.Title, a.Date} into grp
    select new {
        grp.Key.LastName,
        grp.Key.Title,
        grp.Key.Date,
        Plays = grp.Count(),
        Seconds = grp.Sum(x => x.Duration)
    }
);

またはミュージシャンから:

var grpMus = (
    from m in Musicians
    from s in m.Songs
    from p in s.Plays
    where p.Date >= firstDate && p.Date < lastDate
    group p by new {m.LastName, s.Title, p.Date} into grp
    select new {
        grp.Key.LastName,
        grp.Key.Title,
        grp.Key.Date,
        Plays = grp.Count(),
        Seconds= grp.Sum(x => x.Duration)
    }
);

編集: 放送時間のないミュージシャンを含むすべてのミュージシャンを表示するには、別のレベルのグループ化を使用できます。最初のステップでは、曲 + 日ごとの合計を計算し、曲の作者でグループ化します。おそらくデータベースで直接動作する可能性がありますが、効率的な方法を見つけることができませんでした。まだ。;) コードを使用すると、元の AirTimes の結果が変更され、姓の代わりに Musician が返され、すべてのミュージシャンのリストに結合されます。

//Airtimes for musicians
var grpAir = (
    from a in AirTimes
    where a.Date >= firstDate && a.Date < lastDate
    group a by new {a.Song.Musician, a.Date} into grp
    select new {
        //Musician instead of his LastName for joining. Id would work too
        grp.Key.Musician,
        //grp.Key.Musician.LastName,
        Date=grp.Key.Date,
        Plays = grp.Count(),
        Secs = grp.Sum(x => x.Duration)
    }
);

var res = (
    from m in Musicians
    join g in grpAir on m equals g.Musician into g2
    from g in g2.DefaultIfEmpty()
    orderby m.LastName
    select new {
        m.LastName,
        Date = (g==null ? null : g.Date),
        Plays = (g==null ? 0 : g.Plays),
        Secs = (g==null ? 0 : g.Secs)
    }
);

https://gist.github.com/3236238で、より完全な LINQPad サンプルを見つけることができます。

于 2012-08-02T11:00:26.040 に答える