为什么这个 MySQL 查询的结果会相互相乘?
SELECT user_id,
SUM(COALESCE(point_points, 0)) AS total_points,
SUM(
CASE
WHEN point_date > '$this_month'
THEN point_points
ELSE 0
END) AS month_points,
COUNT(DISTINCT c_id) AS num_comments,
COUNT(DISTINCT rant_id) AS live_submissions
FROM users
LEFT JOIN points
ON users.user_id = points.point_userid
LEFT JOIN comments
ON
(
c_userid = user_id
)
LEFT JOIN rants
ON
(
rant_poster = user_id
AND rant_status = 1
)
WHERE user_id = $id
GROUP BY user_id
基本上,live_submissions
和 num_comments
变量显示正确的结果,而 total_points
和 month_points
显示 month_points 的乘积/total_points
、live_submissions
和 num_comments
。 知道为什么会发生这种情况吗?
SELECT user_id,
SUM(COALESCE(point_points, 0)) AS total_points,
SUM(
CASE
WHEN point_date > '$this_month'
THEN point_points
ELSE 0
END) AS month_points,
COUNT(DISTINCT c_id) AS num_comments,
COUNT(DISTINCT rant_id) AS live_submissions
FROM users
LEFT JOIN points
ON users.user_id = points.point_userid
LEFT JOIN comments
ON
(
c_userid = user_id
)
LEFT JOIN rants
ON
(
rant_poster = user_id
AND rant_status = 1
)
WHERE user_id = $id
GROUP BY user_id
Basically live_submissions
and num_comments
variable display proper results, while the total_points
and month_points
display a product of month_points/total_points
, live_submissions
and num_comments
. Any idea why this is happening?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这称为笛卡尔积。 将表连接在一起时,默认结果是连接条件成立的行的每个排列。 您可以使用
JOIN
条件来限制这些排列。但由于您要将多个表连接到
users
,因此结果包括每个匹配表的每个排列。 例如,points
中的每个匹配行都会与comments
中的每个匹配行重复,并且每个匹配行都会再次相乘,从而在rants
中的每个匹配行重复>。您可以像您所做的那样使用
COUNT(DISTINCT c_id)
部分补偿这一点,但DISTINCT
是必需的,只是因为每个c_id
有多个行>。 除非您将其应用于独特的值,否则它不会起作用。 此补救措施不适用于SUM()
表达式。基本上,您试图在一个查询中执行太多计算。 您需要将其拆分为单独的查询才能保证其可靠性。 然后你也可以去掉 DISTINCT 修饰符。
您不应该尝试在单个查询中完成所有这三个操作。
This is called a Cartesian Product. When you join the tables together, the default result is every permutation of rows for which the join conditions are true. You use
JOIN
conditions to limit these permutations.But since you are joining multiple tables to
users
, the result includes every permutation of each matching table. For example, each matching row inpoints
is repeated per matching row incomments
, and each of these is multiplied again, repeating per matching row inrants
.You can partially compensate for this with
COUNT(DISTINCT c_id)
as you are doing, but theDISTINCT
is necessary only because you have multiple rows perc_id
. And it doesn't work unless you apply it to unique values. This remedy doesn't work for theSUM()
expressions.Basically, you're trying to do too many calculations in one query. You need to split it up into separate queries for it to be reliable. And then you can get rid of the
DISTINCT
modifiers, too.You shouldn't try to do all three of these in a single query.
您能提供一些示例输出吗?
我认为这与在观点中添加咆哮和评论有关。 您能尝试删除咆哮和评论表吗?
Can you provide some sample output?
I think it has something to do with adding rants and comments in with the points. Can you try to remove the rants and comments tables?
如果您在分组之前查看查询输出,那么您就会发现问题。 如果用户在任何连接表中拥有超过 1 条记录,则将为用户返回多行。 因此,如果用户有 2 条评论记录,那么也会返回 2 条积分记录。
作为一个简化的例子......
从这些表中选择 * 将导致
我不完全确定 MYSQL 语法,但你会想要类似的东西
If you look at the query output before grouping then you'll see the problem. Multiple rows will be returned for a user if they have more than 1 record in any of the joined tables. So if a user has 2 comment records then 2 point records will also be returned.
As a simplified example...
Selecting * from these tables will result in
I'm not entirely sure of the MYSQL syntax but you would want something like