音乐家写歌。歌曲在空中播放。
我有数据库表“音乐家”、“歌曲”和“AirTimes”。 AirTimes 表条目保存有关哪首歌曲在哪一天播放以及播放了多少分钟的信息。
我有与表相对应的 Musician、Song、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 日更新
我无法确认格鲁多夫的计划是否符合我的要求。我用不同的技术完成了事情。尽管如此,我接受他/她的回答。
最佳答案
由于您具有两个方向的导航属性,因此您可以从 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 结果被更改为返回音乐家而不是他的姓氏,然后加入到所有音乐家的列表中:
//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 示例。
关于linq - 带分组和排序的左连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11773049/