SQL Query:为什么添加另一个表会改变结果?

时间:2013-09-26 16:16:44

标签: mysql sql

我需要一些MySQL的帮助。假设我有这个问题Q1:

Q1:

select cn.idConteudo, TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim)
from navegacaolog nl, conteudoNo cn                  
where nl.idConteudoNo = cn.idConteudoNo AND
TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120

结果如下:

enter image description here

但是如果我将另一个表添加到“from”,让我们说:utilizador table(Q2),结果非常不同,如下图所示:

enter image description here

Q2:

select cn.idConteudo, TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim)
from navegacaolog nl, conteudoNo cn,        utilizador                  
where nl.idConteudoNo = cn.idConteudoNo AND
TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120

我不明白为什么,添加另一个表(不在where子句中使用它)的事实非常重要。有人可以给我一些帮助吗?

亲切的问候

4 个答案:

答案 0 :(得分:4)

您尚未指定连接条件,因此您获得的是FULL CROSS JOIN,它为基表中的每个可能的行组合生成一行。

http://en.wikipedia.org/wiki/Join_(SQL)

我发现使用ANSI语法进行连接可以避免这种混淆。不要只使用FROM子句中的逗号...使用实际的JOIN子句...

select cn.idConteudo, TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim)
from navegacaolog nl
JOIN conteudoNo cn ON nl.idConteudoNo = cn.idConteudoNo
where TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120

答案 1 :(得分:1)

结果没有改变,只是每个结果重复的次数等于新表中的行数。 原因是你在where子句中添加了没有任何连接的新表,因此你有一个交叉连接。

答案 2 :(得分:1)

这是因为您没有意识到您正在使用非ansi SQL连接语法来投射笛卡尔积。

如果您之前有n个结果,那么添加x记录的新表将在逻辑上提供n * x个总结果。

使用ANSI语法更好地了解您的查询(例如https://stackoverflow.com/a/11180050/1291428以查看常见错误)

SELECT cn.idConteudom SUM(uta.pontuacao), SUM(TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim))
FROM navegacaolog nl
    JOIN conteudoNo cn ON nl.idConteudoNo = cn.idConteudoNo AND
TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120
    JOIN utilizador uta ON uta.idUtilizador = nl.idUtilizador 
GROUP BY cn.idConteudo

是您的查询,已标准化。在没有连接条件的情况下加入表(utilizador)意味着实现CROSS JOIN,或者更好地说出笛卡尔积。

答案 3 :(得分:0)

完成。我真正想要的是这样的:

select Q1.idConteudo, Q2.PONTUACAO, Q1.TEMPO
from 
    (select cn.idConteudoNo AS idConteudoNo, cn.idConteudo AS idConteudo,sum(TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim)) AS TEMPO
        from navegacaolog nl
            JOIN conteudoNo cn 
                ON nl.idConteudoNo = cn.idConteudoNo

        where TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120

        group by cn.idConteudoNo) AS Q1

    ,

    (select nl.idConteudoNo AS idConteudoNo, sum(uta.pontuacao) AS PONTUACAO
        from navegacaolog nl
            JOIN utilizadortesteavaliacao uta 
                ON nl.idUtilizador = uta.idUtilizador
        where TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120

        group by nl.idConteudoNo
    ) AS Q2

WHERE

    Q1.idConteudoNo = Q2.idConteudoNo

但你所说的都是正确的。问题是它数次计算的次数相同。

感谢所有

亲切的问候