7

方法一

SELECT o.*, 
       bc.*, 
       s.name  AS plan_name, 
       p.image AS course_image, 
       p.id    AS course_id, 
       p.name  AS course_name, 
       p.id, 
       p.level 
FROM   wg_guru_order o 
       JOIN wg_guru_buy_courses bc 
         ON o.id = bc.order_id 
       JOIN wg_guru_subplan s 
         ON bc.plan_id = s.id 
       JOIN wg_guru_program p 
         ON bc.course_id = p.id 
WHERE  o.status = 'Paid' 
       AND bc.userid = 451 
        OR p.catid = 26 
           AND p.published = 1

EXPLAIN 命令输出

在此处输入图像描述

方法二

 SELECT o.*,
       bc.*,
       s.name  AS plan_name,
       p.image AS course_image,
       p.id    AS course_id,
       p.name  AS course_name,
       p.id,
       p.level
FROM   wg_guru_order o,
       wg_guru_buy_courses bc,
       wg_guru_subplan s,
       wg_guru_program p
WHERE  o.status = 'Paid'
       AND o.id = bc.order_id
       AND bc.userid = 451
       AND bc.plan_id = s.id
       AND bc.course_id = p.id
        OR p.catid = 26
           AND p.published = 1 

EXPLAIN 命令输出

在此处输入图像描述

以上两个是相同的,恰好对我来说工作正常。唯一的区别是方法 1 查询是使用JOIN子句 &编写ON的,方法 2 是使用JOIN速记方法编写的。

问题是方法 1 返回 3 行,方法 2 返回 1543 行。相同的查询如何返回不同的结果?

鉴于我只想了解为什么会这样。我不关心结果集。我想知道的是,以两种方式编写的相同查询如何输出不同类型的结果集?

4

2 回答 2

11

您的问题不是 CROSS JOIN 与 INNER JOIN,而是您的 WHERE 标准需要在适当的 OR 子句周围加上括号。

方法 2应该有这样的子句WHERE,相当于方法 1:

WHERE ( o.id = bc.order_id
    AND bc.plan_id = s.id
    AND bc.course_id = p.id
    )
  AND ( o.status = 'Paid' AND bc.userid = 451
     OR p.catid = 26 AND p.published = 1
      )
于 2013-01-24T15:13:41.433 回答
4

总是更喜欢第一个选项。

这两个选项都是标准的,但第二个选项来自较旧的 SQL-89 标准。第一个选项是新的 SQL-92 标准。旧标准已弃用,一些数据库开始遵循该弃用标准。例如,Sql Server 2012 放弃了对通过旧语法进行外连接的支持。MySQL 仍然完全支持它,但你不应该真的指望它在你的应用程序的生命周期中保持这种状态。

除此之外,这些不是相同的查询。您需要在 WHERE 子句中添加一些括号来控制如何OR解释您的条件。这就是查询返回不同行集的原因。如所写,就好像您的 where 子句如下所示:

方法一:

WHERE  (o.status = 'Paid' AND bc.userid = 451)
    OR (p.catid = 26 AND p.published = 1)

方法二:

WHERE 
   (o.status = 'Paid'
      AND o.id = bc.order_id
      AND bc.userid = 451
      AND bc.plan_id = s.id
      AND bc.course_id = p.id
   ) OR ( p.catid = 26 AND p.published = 1)

注意分组......这可能不是你想要的。我希望你打算更像这样:

WHERE  o.status = 'Paid'
  AND  o.id = bc.order_id
  AND  bc.course_id = p.id
  AND  bc.plan_id = s.id
  AND (bc.userid = 451 OR p.catid = 26)
  AND  p.published = 1

现在你的查询都不是这样工作的,但我认为它更接近你真正想要做的事情。您需要在正确的位置使用括号编写查询以获得所需的结果。

于 2013-01-24T15:13:23.143 回答