同一张表上的多个连接,在一个查询中计数

Posted

技术标签:

【中文标题】同一张表上的多个连接,在一个查询中计数【英文标题】:Multiple joins on the same table with counting in one query 【发布时间】:2015-09-10 22:56:22 【问题描述】:

我有一个关于两次加入同一个表的 SQL 查询的基本问题。这听起来很简单,但我有一些麻烦。我希望,任何人都可以帮助我解决这个问题:)

我有两个小表:“peoples”(列:id、name、...)和“likes”(id、who、whom)。人们可以互相设置“喜欢”。这种关系是多对多的。 我想得到人们喜欢的桌子:收到的“喜欢”的数量,交付的数量和相互喜欢的数量。 当我只使用一个连接时,一切都是正确的。但是对于两个连接(或更多),mysql 合并所有行(如预期的那样)并且我得到错误的计数值。我不知道,在这种情况下我必须如何使用 count/sum/group-by 运算符:( 我想在一个查询中不使用子查询。

我使用了这样的查询:

SELECT *, count(l1.whom), count(l2.whom)
FROM people p
LEFT JOIN likes l1 ON l1.who = p.id
LEFT JOIN likes l2 ON l2.whom = p.id
GROUP BY p.id;

SELECT p.id, name, 
   count(lwho.who) delivered_likes, 
   count(lwhom.whom) received_likes, 
   count(lmut.who) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON lwhom.id = lwho.id
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id;

但它计算的点赞数不正确。

这只是训练的问题,性能并不重要,但我想,我上次查询中的三个连接太多了。我可以使用 2 个连接吗?

提前感谢您的帮助。

【问题讨论】:

您的加入看起来不错。但是,您应该确保按查询中未聚合的所有列进行分组。您没有在第二个查询中按 name 分组。我无法忍受 MySQL 允许这样做。 【参考方案1】:

我推测peoplelikes之间存在1:N的关系。

据我所知,第二个查询的一个问题是likeslwhom 相关性通过id=id 连接到lwho。基本上lwhom lwho。我建议将此关联的 ON 子句从 lwhom.id = lwho.id 更改为 p.id = lwhom.whom

但是,计数仍会受到 JOIN 的影响。但是,假设您在 likes 表中有一个 ID 列,那么您可以让每个 COUNT 计算每个人的不同 Like ID - 如果没有,请考虑只使用 COUNT(DISTINCT correlation.*)

抛开题外话,以下应该可以工作:

SELECT p.id, name, 
   count(distinct lwho.id) delivered_likes, 
   count(distinct lwhom.id) received_likes, 
   count(distinct lmut.id) mutual_likes
FROM people AS p
LEFT JOIN likes AS lwho ON p.id = lwho.who
LEFT JOIN likes AS lwhom ON p.id = lwhom.whom
LEFT JOIN likes AS lmut ON lwhom.who = lmut.whom AND lwhom.whom = lmut.who
GROUP BY p.id,p.name;

我有一个 SQL Fiddle here。

【讨论】:

嗨,亚当。非常感谢您的回答和示例。它也适用于我。它帮助我理解我的错误。应该小心几个连接和分组:) PS 当然,关系是 1:N - 一个人和更多的喜欢。这是我在描述中的可悲错误。

以上是关于同一张表上的多个连接,在一个查询中计数的主要内容,如果未能解决你的问题,请参考以下文章

同一张表上的多个连接:转换状态

在同一个表上具有多个连接的 Oracle 复杂查询

SQL:同一表上的多个连接的性能

同一张表上的多个事务,同时

更新查询在同一张表上的 Sql 查询死锁

三张表上的 Ormlite 内连接