【问题标题】:Get group by records from many to many relationship table从多对多关系表中获取分组记录
【发布时间】:2015-05-22 12:10:43
【问题描述】:

我有 3 张桌子,Person | Book | PersonBook
PersonBook 表是PersonBook 之间的关系表

Person          Book                    PersonBooks
Id   Name       Id     Name             Id   PersonId   BookId
1    rick        1      SQL              1     1          1
2    phil        2      Asp.Net          2     1          3
3    scott       3      MySql            3     2          4 
                 4      C#               4     3          2
                                         5     3          3
                                         6     3          4

我想得到阅读书籍 id 2、3、4 的人。因此结果应该是 3。

我试过什么

我设法编写 sql 查询来获得结果。但我想要 Linq 查询这个。
我的sql查询是

SELECT DISTINCT(PersonId) From PersonBooks
WHERE BookId IN (2, 3, 4)
GROUP BY PersonId
HAVING COUNT (*) = 3

sql 查询如果工作正常。但我想为此使用 linq 查询。任何帮助都会被应用

更新

这个查询对我有用,但我认为它没有经过优化。谁能帮我优化这个查询。

from p in Context.Book where (Context.PersonBooks.Where(x => personIds.Contains(x.PersonId))
    .GroupBy(x => x.BookId)
    .Where(x=>x.Count() == personIds.Count)
    .OrderByDescending(x => x.Count())
    .Select(x => x.Key).ToList()).Contains(p.BookId) select p;

【问题讨论】:

  • 我不认为你的查询工作正常,你需要 FROM 而你不需要 Distinct。
  • @Tim3880 抱歉拼写错误:)
  • @Tim3880 实际上我需要不同的,这不是原始表,只是演示数据没有不同的我得到错误。原始表还包含许多其他列。

标签: c# sql-server linq many-to-many entity-framework-6


【解决方案1】:
var person = (from p in PersonBooks
                  join b in Book on p.BookId equals b.BookId
                  where b.BookId  IN (2, 3, 4)
                  select new { p.PersonId});

【讨论】:

  • 您不需要Book,因为PersonBook 已经有BookId。此外,IN 在 LINQ 语法中不存在。
  • 是的,我忽略了这一点。谢谢@GertArnold
【解决方案2】:

像往常一样,人们在 LINQ 中跳转加入语法,但您绝对应该使用导航属性:

var ids = new[] { 2, 3, 4 };
var persons = from p in db.Persons
              where p.PersonBooks.All(pb => ids.Contains(pb.BookId))
                 && p.PersonBooks.Count() == 3
              select p;

这转换为 EXIST 子句,因此您不再需要 Distinct。它还会根据您的需要返回 Persons,而不仅仅是 ID。

顺便说一句,如果您希望人们阅读至少一本(不是全部)书籍,您可以将All 替换为Any

【讨论】:

  • 它无法显示由任何选定 ID 阅读的所有书籍。
  • 是的,我在我的问题中指定了这一点,我想要阅读所有书籍而不是至少一本的人。
  • 我不明白。您能否将生成的 SQL(使用 All 语句)发布到您的问题中?
  • 好吧,现在问题不同了。我修改了我的查询,使其包含计数。现在它选择阅读所有书籍的人,而不仅仅是ids中的一些书籍。
【解决方案3】:

试试这个……

from bp in BookPerson
join p in person on p.personId== bp.personId
join b in books on b.bookId == bp.bookId
where b.bookId = 1 && b.bookId = 2 && b.bookId = 3
group p by bp.personId into p
select new {g.personId};

【讨论】:

  • 您不需要连接。您可以单独使用PersonBook 完成所有操作。请注意,b.bookId = 1 && b.bookId = 2 && b.bookId = 3 绝不是 true。并且:group ... into p 是一个类型,分组(g)没有personId
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-18
  • 2014-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-22
相关资源
最近更新 更多