7

方法1

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コマンド出力

ここに画像の説明を入力してください

方法2

 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コマンド出力

ここに画像の説明を入力してください

上記の2つは同じで、たまたまうまく機能しています。唯一の違いは、メソッド1のクエリはJOINclaues&を使用してON記述され、メソッド2はJOIN省略形のメソッドを使用して記述されることです。

問題は、メソッド1が3行を返し、メソッド2が1543行を返すことです。同じクエリが異なる結果を返すにはどうすればよいですか?

なぜそうなのかを理解したいだけです。結果セットについては気にしません。2つの方法で記述された同じクエリが、異なるタイプの結果セットをどのように出力できるのでしょうか。

4

2 に答える 2

11

問題は、CROSSJOINとINNERJOINではなく、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

常に最初のオプションを優先します。

どちらのオプションも標準ですが、2番目のオプションは古いSQL-89標準のものです。最初のオプションは、新しいSQL-92標準です。古い標準は非推奨になり、一部のデータベースはその非推奨に対応し始めています。たとえば、SQL Server 2012は、古い構文を介して外部結合を実行するためのサポートを終了しました。それはまだMySQLによって完全にサポートされていますが、アプリケーションの存続期間中、そのように維持されることを実際に期待するべきではありません。

これを超えて、それらは同じクエリではありません。OR条件の解釈方法を制御するには、WHERE句にいくつかの括弧を追加する必要があります。これが、クエリが異なる行のセットを返す理由です。書かれているように、where句は次のようになります。

方法1:

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

方法2:

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 に答える