为什么这个MySQL查询的结果得到彼此相乘?
-
22-08-2019 - |
题
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
的产物。任何想法,为什么发生这种情况?
解决方案
此被称为笛卡尔积。当您加入表一起,默认的结果是行的每一个排列作为其加入条件为真。您可以使用JOIN
条件限制这些排列。
但是,因为要加入多个表以users
,结果包括每个匹配表中的每个排列。例如,在points
每个匹配行每行匹配重复comments
,并且每个这些被再次相乘,每在rants
匹配行重复。
您可以部分地为这个与COUNT(DISTINCT c_id)
补偿,你在做什么,但DISTINCT
是必要的,只是因为你必须每c_id
多行。它不工作,除非你把它应用到独特的价值。这个补救措施没有为SUM()
表达式工作。
基本上,你想在一个查询做太多的计算。您需要将它分割成单独的查询它是可靠的。然后你就可以摆脱DISTINCT
改性剂,也。
SELECT u.user_id, SUM(COALESCE(p.point_points, 0)) AS total_points,
SUM( CASE WHEN p.point_date > '$this_month' THEN p.point_points ELSE 0 END ) AS month_points
FROM users u LEFT JOIN points p
ON u.user_id = p.point_userid
WHERE u.user_id = $id
GROUP BY u.user_id;
SELECT user_id, COUNT(c.c_id) as num_comments,
FROM users u LEFT JOIN comments c
ON (c.c_userid = u.user_id)
WHERE u.user_id = $id
GROUP BY u.user_id;
SELECT u.user_id, COUNT(r.rant_id) as live_submissions
FROM users u LEFT JOIN rants r
ON (r.rant_poster = u.user_id AND r.rant_status = 1)
WHERE u.user_id = $id
GROUP BY u.user_id;
您不应该尝试做所有这三个在一个单一的查询。
其他提示
你能提供一些示例输出?
我认为这是与同分加咆哮和意见。你可以尝试删除咆哮和意见表?
如果您分组,然后你会看到这个问题之前,我们看看这个查询输出。多行将会返回一个用户,如果他们有任何连接表超过1分的纪录。因此,如果用户有2个评论记录然后2个记录也将被退回。
作为简化实例...
用户表
用户id名称
1佛瑞德
点表
用户id点数
1 10
评论表
用户id注释
1这里
1有
选择*从这些表将导致
用户id点注释
1 10在这里
1 10有
我不能完全肯定MYSQL语法,但你会希望类似
SELECT UserId, C.num_comments, P.total_points
FROM users
LEFT JOIN
(SELECT c_userId, COUNT(DISTINCT c_id) as num_comments
FROM Comments
GROUP BY c_userId)
AS C
ON UserId = c_userid
LEFT JOIN
(SELECT point_userId, sum(COALESCE(point_points, 0)) as total_points
FROM Points
GROUP BY point_userId)
AS P
ON UserId = point_userid
不隶属于 StackOverflow