添加左联接后,计数相乘

时间:2019-07-16 00:37:30

标签: mysql sql

在我的查询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

3 个答案:

答案 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,将从fs的多个成功联接再次 联接。

要修复,请使用t

count(distinct ...)