【问题标题】:SQL Query: why does adding another table change the results?SQL 查询:为什么添加另一个表会改变结果?
【发布时间】:2013-10-02 17:30:08
【问题描述】:

我需要一些有关 MySQL 的帮助。假设我有这个查询 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

结果如下:

但是,如果我将另一个表添加到“来自”,让我们说:utilizador 表(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 子句中使用)这一事实非常重要。有人可以帮帮我吗?

亲切的问候

【问题讨论】:

  • 你的另一个表是否有相同的字段?也许您可以尝试将它们与 Join 结合,我认为这不是一个明确的查询

标签: mysql sql


【解决方案1】:

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

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

但是你说的都是对的。问题是它计算了多次相同的东西。

谢谢大家

亲切的问候

【讨论】:

    【解决方案2】:

    这是因为您没有意识到您正在使用非 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,或者更好地说是笛卡尔积。

    【讨论】:

    • 嗯,我想要做这样的事情:select cn.idConteudo, SUM(uta.pontuacao), SUM(TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim)) from navegacaolog nl, conteudoNo cn, utilizadortesteavaliacao uta where nl.idConteudoNo = cn.idConteudoNo AND TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120 AND uta.idUtilizador = nl.idUtilizador group by cn.idConteudo 我试图使用连接来做到这一点,但是,到目前为止,我得到的结果是 Jasmine 的答案。我现在想调整它来做我上面写的。我该怎么做?
    • 我的想法是这样的:SELECT cn.idConteudo, 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 CROSS JOIN utilizadortesteavaliacao uta where uta.idUtilizador = nl.idUtilizador group by cn.idConteudo 但它也不起作用:(
    【解决方案3】:

    您没有指定连接条件,因此您得到的是 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
    

    【讨论】:

    • 如果我想添加另一个表?:原始查询是这样的:` select cn.idConteudo, SUM(uta.pontuacao), SUM(TIMESTAMPDIFF(SECOND, nl.dataInicio, nl .dataFim)) 来自 navegacaolog nl, conteudoNo cn, utilizadortesteavaliacao uta ` 其中 nl.idConteudoNo = cn.idConteudoNo AND TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120 AND uta.idUtilizador = nl.idUtilizador`
    • 然后添加另一个连接子句和条件。您可以拥有任意数量的 JOIN。
    • 所以,像这样:select cn.idConteudo, sum(TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim)) from navegacaolog nl JOIN conteudoNo cn ON nl.idConteudoNo = cn.idConteudoNo JOIN utilizadortesteavaliacao uta ON nl.idUtilizador = uta.idUtilizador where TIMESTAMPDIFF(SECOND, nl.dataInicio , nl.dataFim) > 120 group by cn.idConteudo 对吗?不幸的是它仍然不起作用,我认为时间戳的总和不应该产生如此高的值
    • 是的,这就是它应该做的。如果您在第一个表中有一行与第二个表中的两行匹配,您将获得两行输出。如果您只想数一个,则必须使用一些分组。
    【解决方案4】:

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

    【讨论】:

    • 嗯,好的,我明白了。所以你告诉我,我必须在它们之间建立关系才能获得相同的结果。写?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多