嵌套 MySQL 查询的解决方法
本文关键字:解决 方法 查询 MySQL 嵌套 | 更新日期: 2023-09-27 18:33:59
以下代码段是伪代码 - 数据库结构没有任何问题。我正在使用数据库优先方法,并且它们已经证明工作正常。
请考虑下表;
public class Blog
{
public int Id { get; set; }
public string Content { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public string UserName { get; set; }
public int BlogId { get; set; }
public string Content { get; set; }
public virtual Blog Blog { get; set; }
}
假设我想抓取用户发布两次(或更多(的所有Blogs
。考虑到MyDbContext
是一个DbContext
,我会这样做;
using(var context = new MyDbContext)
{
var doublePosters = context.Blog.Where(b => b.Posts.GroupBy(p => p.UserName).Any(x => x.Count() > 1));
foreach(var poster in doublePosters)
{
//Do things with it
}
}
反过来,由于我使用的是 EF6 和 MySQL 数据库,因此IQueryable<>
将如下所示;
SELECT `Extent1`.`Id`, `Extent1`.`Content`
FROM `Blog` AS `Extent1`
WHERE EXISTS
(
SELECT 1 AS `C1`
FROM
(
SELECT
`Extent2`.`UserName` AS `K1`, COUNT(1) AS `A1`
FROM `Post` AS `Extent2`
WHERE `Extent1`.`Id` = `Extent2`.`BlogId`
GROUP BY `Extent2`.`UserName`
) AS `GroupBy1`
WHERE `GroupBy1`.`A1` > 1
)
但是,MySQL不能很好地处理这个问题,因为它返回
SQL 错误 (1054(:"where 子句"中的未知列"Extent1.Id"
我已经认为这是MySQL的限制,因此我的问题是如何在不严重打击数据库的情况下获得相同的结果?
当然,一个选项是查询整个Blog
表,将其放入List<>
中,然后让 LINQ 完成其余的工作。但是,我的Blog
表包含 ~500000 条记录 - 获取所有记录不是一个好主意。
编辑
一些样本数据和预期数据;
博客:
+----+---------+
| Id | Content |
+----+---------+
| 1 | "blabla"|
| 2 | "albalb"|
+----+---------+
发布:
+--------+----------+---------+
| BlogId | UserName | Content |
+--------+----------+---------+
| 1 | Jon | "Nice!" |
| 1 | Jon | "Well.."|
| 1 | Jon | "Nvm." |
| 1 | Sam | "Ok!" |
| 1 | Sam | "Good." |
| 1 | Robert | "Sweet" |
| 2 | Robert | "Nah" |
| 2 | Jonah | "Hey" |
+--------+----------+---------+
查询的预期输出:
+----+---------+
| Id | Content |
+----+---------+
| 1 | "blabla"|
+----+---------+
因为只有 Blog
1 有一张发帖多次的海报(看着你、乔恩和山姆(。
这种方法呢(将查询分成两部分(?
var posts= context.Posts.GroupBy(p => p.UserName).Any(x => x.Count() > 1).Select(y=>y.BlogId).ToList();
var doublePosters = context.Blog.Where(b=> posts.Contains(b.Id));
foreach(var poster in doublePosters) {
//Do things with it
}
我不确定这种方法的性能(代码未测试(,也许它可以成为解决问题的新方法的起点。
我的建议是
- 获取某人多次发布内容的博客的所有 ID。
- 按上一个查询的 ID 筛选博客
更新
尝试此代码以实现您的目标
var postIds = context.Posts.GroupBy(p => new {p.BlogId,p.UserName}).Where(x=> x.Count() > 1).Select(el=> el.Key.BlogId);
var doublePosters = context.Blog.Where(b => postIds.Contains(b.Id)).ToList();
关键是按BlogId和用户名分组