我有以下3个表: -
在编写以下查询时,由于笛卡尔积,我输出错误: -
SELECT C.name customer, SUM(A.achieved) achived, SUM(T.target) target
FROM customers C
LEFT JOIN achieved A
ON C.customer_id = A.customer_id
LEFT JOIN target T
ON C.customer_id = T.customer_id
GROUP BY customer
使用LEFT join获得正确结果的正确方法是什么?
答案 0 :(得分:0)
我理解,因为您要加入achieved
和target
加入customer
,您将获得achieved
无意义的笛卡尔积和target
。
您可以暂时删除SUM
以查看问题的原因。
如果没有SUM
,此查询会为您提供不必要的大型结果集。 使用 SUM
时,重复的值都会对总和产生影响,从而创建一个大于预期的值。
您可以通过加入常量序列强制MySQL将连接的表分开,如下所示。
SELECT C.name customer, SUM(A.achieved) achieved, SUM(T.target) target
FROM customers C
# Split every customer into two rows, joinType=1 vs. joinType=2
LEFT JOIN (SELECT 1 AS joinItem UNION ALL SELECT 2) AS joinItems
ON TRUE
# Join achieved only where joinType=1 (will be NULL elsewhere)
LEFT JOIN achieved A
ON joinItem = 1 AND C.customer_id = A.customer_id
# Join target only where joinType=2 (will be NULL elsewhere)
LEFT JOIN target T
ON joinItem = 2 AND C.customer_id = T.customer_id
GROUP BY customer
现在,已实现和目标将不再相互增加。
EXPLAIN
应该确认这仍然有效处理。
注意:最初,这会为每个匹配的“已实现”(“目标”数据为NULL)创建一个客户记录,并为每个匹配的“目标”添加一个单独的客户记录(“已实现”数据为NULL)。然而,这个场景中的GROUP BY
会将它们重新组合回每个客户的单个记录中,并且具有我们想要的数据。
答案 1 :(得分:-1)
您也可以试试这个......
SELECT C.name customer, SUM(A.achieved) achived, SUM(T.target) target
FROM customers C,achieved A,target T
WHERE C.customer_id = A.customer_id
AND C.customer_id = T.customer_id
AND A.customer_id = T.customer_id
GROUP BY C.customer