3

なぜこのクエリがまだ完全に機能するのだろうか。WHEREWHERE 句は常に?で始まる必要があると思いました。

    SELECT `persons`.*
    FROM `persons`
    LEFT JOIN `team_memberships`
    ON (`team_memberships`.`participant` = `persons`.`id`)
    JOIN `teams`
    ON (`teams`.`id` = `team_memberships`.`team`)
    JOIN `departments`
    ON (`departments`.`id` = `teams`.`department`)
    JOIN `areas`
    ON (`areas`.`id` = `departments`.`area`)
    JOIN `companies`
    ON (`companies`.`id` = `areas`.`company`)

    [NO WHERE HERE]

    AND `persons`.`id` = ?
4

6 に答える 6

6

節に anANDを追加しました。ONこのON句はブール値の true または false に評価されるだけなのでAND、たとえばORブール演算子が許可され、括弧などに関するすべての通常の規則も適用されます。

特定の結合テーブルに固有の条件を句からWHERE適切なON句に移動すると、多くの場合、有利になります (読みやすさを向上させる以外の理由がない場合)。

大きな結果セットを返し、最後に句でこれをフィルタリングするのではなく、他のテーブルに結合するに結合の結果を制限することは論理的に*意味があります。WHERE*logical と言うのは、多くの場合、DBMS がクエリを最適化して、とにかくこれが発生するようにするためです...ただし、常にではありません...パフォーマンスの低いクエリは、結合でフィルタリングすることで改善できる場合があります (逆の場合もあります)。

たとえば、25 歳以上の人にのみ関心があることがわかっている場合は、若いパンクスのみに関連する後続のテーブルのすべてJOIN persons ON persons.id = team_memberships.participant AND persons.age > 25の結果を含めて、最後にこれらの結果のみを再度フィルター処理するのではなく、あなたの条項で。WHERE persons.age > 25

私の理解では、追加の式ONが次の場合に、節に追加の式が追加された結果、結合のパフォーマンスが低下する可能性があります。

  • 結合の各行で評価が行われるようにする (age > 25上記の例はこのカテゴリに含まれる可能性があります)。

  • 結合がインデックス付きの列のみに依存していた場合に、一方または両方の結合されたテーブルのインデックス付きでない列に依存します。

したがって、たとえば、特定の結合が遅くなったとしても、結合時に結果セットから若いパンクを削除する価値があると証明される場合があります。その時点での結果セットが小さいと、後続の結合のパフォーマンスが大幅に向上する可能性があるためです。ただし、結合でそれらを含めてもレコード数がわずかに増加するだけの場合は、結合でそれらを含めてからWHERE句で除外する方が実際には速い場合があります。

しかし、私の理解を明確化/修正するコメントを歓迎します。


編集:以下の @ITroubs コメントに従って、結合が anINNER JOINの場合、追加のフィルター条件がONorWHERE句にあるかどうかに関係なく、最終的な結果セットは同じになることを明確にする必要がありましたが、たとえば OP の元の例でLEFT JOIN ON team_membershipsは、フィルタ条件を から に移動すると、まったく異なる結果セットが生成WHEREされLEFT JOIN ... ON ...ます。

于 2013-03-20T14:54:27.720 に答える
2

私が間違っていない場合、mysqlは次のようにクエリを実行します。

SELECT `persons`.*
FROM `persons`
LEFT JOIN `team_memberships`
ON (`team_memberships`.`participant` = `persons`.`id`)
JOIN `teams`
ON (`teams`.`id` = `team_memberships`.`team`)
JOIN `departments`
ON (`departments`.`id` = `teams`.`department`)
JOIN `areas`
ON (`areas`.`id` = `departments`.`area`)
JOIN `companies`
ON ((`companies`.`id` = `areas`.`company`) AND `persons`.`id` = ?')
于 2013-03-20T14:54:15.290 に答える
0

最後の AND は WHERE 句の一部ではなく、JOIN 句の一部です

于 2013-03-20T14:54:43.550 に答える
0

WHERE実際には句がないため機能します。条件AND persons.id = ?は最後の一部ですJOIN

于 2013-03-20T14:54:47.367 に答える
0

それは効果的に意味します

join  `companies` on ON (`companies`.`id` = `areas`.`company`) AND persons.id = ?

したがって、内部結合を実行しているため、*ほぼ*同等です。puter 結合または複雑なクエリに切り替えるとすぐに、何かが壊れます。

于 2013-03-20T14:55:28.523 に答える
-1

有効です。http://dev.mysql.com/doc/refman/5.0/en/join.htmlを参照してください。ただし、ブラケットの使用方法に注意してください。

于 2013-03-20T14:55:49.273 に答える