在我的查询http://www.sqlfiddle.com/#!9/16b9c2/3/0
中SELECT f.name, COUNT(s.letters), AVG(t.numbers)
FROM first f
INNER JOIN second s
ON s.first_id = f.id AND s.letters IN ('aa', 'bb', 'cc', 'dd')
LEFT JOIN third t
ON t.first_id = f.id
GROUP BY f.id
在加入第三张桌子之前,计数为 4-1-,但是在加入第三张桌子之后,计数变为 16-1 ,这是错误的,因为它必须是 4-1
答案 0 :(得分:2)
您的平均值也可能微不足道-或至少需要进行其他不必要的计算。
原因是行数沿两个维度相乘。更为准确的解决方案是在进行join
之前先汇总 :
SELECT f.name, s.num_letters, AVG(t.numbers)
FROM first f INNER JOIN
(SELECT s.first_id, COUNT(*) as num_letters
FROM second s
WHERE s.letters IN ('aa', 'bb', 'cc', 'dd')
GROUP BY s.first_id
) s
ON s.first_id = f.id LEFT JOIN
third t
ON t.first_id = f.id
GROUP BY f.id, s.num_letters;
对于此类查询,最好将所有聚合移入子查询:
SELECT f.name, s.num_letters, t.avg_numbers
FROM first f INNER JOIN
(SELECT s.first_id, COUNT(*) as num_letters
FROM second s
WHERE s.letters IN ('aa', 'bb', 'cc', 'dd')
GROUP BY s.first_id
) s
ON s.first_id = f.id LEFT JOIN
(SELECT t.first_id, AVG(t.numbers) as avg_numbers
FROM third t
GROUP BY t.first_id
) t
ON t.first_id = f.id;
答案 1 :(得分:1)
有点难看,但是得到答案: http://www.sqlfiddle.com/#!9/16b9c2/26
SELECT s2.name, s2.letters, AVG(t.numbers)
FROM (
select f.id, f.name as name, COUNT(s.letters) as letters
from first f
JOIN second s
ON s.first_id = f.id AND s.letters IN ('aa', 'bb', 'cc', 'dd')
GROUP BY f.id) s2
JOIN third t
ON t.first_id = s2.id
group by s2.name;
在您的情况下,是左联接还是联接还是内部联接都没有区别,因为每个值都是可联接的。之所以发生“扇出”,是因为数字和字母上没有连接条件,因此它们实际上是交叉连接的。
建议的解决方案采用两个分组依据,通过在每个级别进行聚合来消除交叉。
答案 2 :(得分:0)
对返回的每一行进行计数,因此对于每个成功的联合classification
,将从f
到s
的多个成功联接再次 联接。
要修复,请使用t
:
count(distinct ...)