24


4

次のような質問があります。

SELECT c。*会社からAS cユーザーを使用してu(companyid)を使用してジョブをj jを使用して(userid)JOIN useraccountsを使用してUS(userid)を使用WHERE j.jobid = 123;

以下の質問があります。

  1. USING構文はON構文と同義語ですか?

  2. これらの結合は左から右に評価されますか? 言い換えれば、このクエリは言うのですか? y = xジョブを結合します。 z = yユーザーアカウントに参加。

  3. 質問2の答えが「はい」の場合、会社の表にcompanyid、userid、およびjobidの列があると仮定しても安全ですか?

  4. それが別名 "j"を参照しているとき、WHERE句を使用してcompanyテーブルの行を選択する方法がわかりません。

任意の助けは大歓迎です!

7 Answer


25


  1. USING(fieldname)はON table1.fieldname = table2.fieldnameを表す簡単な方法です。

  2. SQLはJOINSが行われる「順序」を定義しません。これは言語の性質ではないためです。 ステートメント内で順序を指定する必要があることは明らかですが、INNER JOINは交換可能と見なすことができます。それらを任意の順序でリストすることができ、同じ結果が得られます。 とはいえ、SELECTを構築するときは…​ JOIN、特にLEFT JOINを含むJOINは、3番目のJOINを新しいテーブルに最初のJOINの結果に結合し、4番目のJOINを2番目のJOINの結果に結合するというように考えるのが理にかなっています。 ごくまれに、指定された順序がヒューリスティックに影響を与える方法のために、クエリオプティマイザの動作に影響を与える可能性があります。

  3. いいえ 照会の組み立て方法は、会社とユーザーの両方が会社IDを持ち、jobsがユーザーIDとjobidを持ち、useraccountsがユーザーIDを持つことを必要とします。 ただし、JOINが機能するには、ユーザーIDが必要なのは1社のみです。

  4. WHERE句は結果全体をフィルタリングしています。 すべてのJOIN列 - jobsテーブルによって提供される列を使用します。


10


USING構文についてはちょっと答えられません。 それは変だ。 今まで見たことがないので、代わりにON句を常に使用しました。

しかし、私が言うことができるのは、JOIN操作の順序は、最適化ヒューリスティックのシステムに基づいて、クエリプランを構築するときにクエリオプティマイザによって動的に決定されるということです。

  1. JOINは主キーフィールドで実行されますか? もしそうなら、これはクエリプランで高い優先順位を取得します。

  2. JOINは外部キー項目に対して実行されますか? これも最優先事項です。

  3. 結合フィールドに索引がありますか? もしそうなら、優先順位を上げる。

  4. WHERE句のフィールドに対してJOIN操作が実行されていますか? WHERE句の式は、(テーブルスキャンを実行するのではなく)インデックスを調べることで評価できますか? これは大部分の最適化の機会であるため、最も優先順位が高くなります。

  5. 結合列の基数は何ですか? カーディナリティの高い列を使用すると、オプティマイザは誤った一致(WHERE句またはON句を満たさないもの)を区別する機会が多くなるため、通常、カーディナリティの高い結合はカーディナリティの低い結合の前に処理されます。

  6. 結合テーブルに実際の行はいくつありますか。 たった100個の値を持つテーブルに対して結合することは、1000万行を持つテーブルに対して結合することより少ないデータ爆発を生み出すことになるでしょう。

とにかく… ポイントは…​ クエリ実行プランに入る変数はたくさんあります。 MySQLがどのようにクエリを最適化するのかを知りたい場合は、EXPLAIN構文を使用してください。

そしてここに読むべき良い記事があります:

'' '' '

編集中:

あなたの4番目の質問に答えるには:あなたは「会社」テーブルに問い合わせていません。 FROM句とUSING句内の* ALL * 4つのテーブルの結合クロス積をクエリしています。

"j.jobid"エイリアスは、結合されたテーブルのコレクション内のいずれかの列の完全修飾名です。


2


MySQLでは、クエリオプティマイザに何をする予定なのかを尋ねるのがおもしろいです。

EXPLAIN SELECT [...]
http://dev.mysql.com/doc/refman/5.0/en/using-explain.html["7.2.1 EXPLAINを使用したクエリの最適化 "]を参照してください。


0


ANDここから読み始めてください:

'' '' '

  • MySQL 5.0.12での結合処理の変更

MySQL 5.0.12から、自然結合および外部結合の変形を含むUSINGによる結合は、SQL:2003標準に従って処理されます。 目標は、NATURAL JOINとJOINに関してMySQLの構文と意味を一致させることでした…​ SQL:2003に従って使用しています。 ただし、結合処理におけるこれらの変更により、一部の結合について異なる出力列が生じる可能性があります。 また、古いバージョンで正しく機能するように見えたいくつかのクエリは、標準に準拠するように書き直す必要があります。

これらの変更には5つの主な側面があります。

  • MySQLがNATURALまたはUSING結合操作の結果列(したがってFROM節全体の結果)を決定する方法。

  • SELECT *およびSELECT tbl_name。*を選択された列のリストに拡張します。

  • NATURALまたはUSING結合での列名の解決

  • NATURALまたはUSINGの変換がJOINに結合します…​ に。

  • 結合のON条件での列名の解決…​ に。


0


ONとUSINGの部分についてはよくわかりません(ただし、 webサイトは同じです)。

順序付けの質問に関しては、その完全な実装(そしておそらく問い合わせ)特有のものです。 MYSQLはおそらくリクエストをコンパイルするときに注文を選択します。 特定の順番を強制したい場合は、クエリを「ネスト」する必要があります。

SELECT c。* FROM会社AS c JOIN(SELECT * FROMユーザーAS u JOIN(SELECT * FROMジョブAS j USING(userid)JOIN useraccounts AS AS USING(userid)WHERE j.jobid = 123))

パート4と同様に、where節は、jobsテーブルのどの行にJOINをかけることができるかを制限します。 そのため、一致するユーザーIDのために結合するが正しいジョブIDを持たない行がある場合、それらは省略されます。


0


1)usingはonと全く同じというわけではありませんが、両方のテーブルが同じ名前のカラムを持っているのは簡単です…​ http://www.java2s.com/Tutorial/MySQL/0100__Table-Join/キーワードUSINGは、tableJoins.htmの間のONキーワードの置き換えとして使用できます。

私の意見を読むのはもっと難しいので、結合をつづりに行きます。

3)この問い合わせからは明らかではありませんが、そうではないと思います。

2)他のテーブルを介して参加していると仮定すると(企業内で直接行われるわけではありません)、このクエリの順序は重要です…​ 下記の比較を参照してください。

オリジナル:

SELECT c。*会社からAS cユーザーからの使用ユーザー(companyid)の使用方法ジョブj AS(ユーザーID)の使用useraccounts ASとしての使用(userid)WHERE j.jobid = 123

私はそれがおそらく示唆していると思います:

SELECT c。*会社からcユーザーからu.companyid = c.companyidにジョブを登録jにj.userid = u.useridにジョブを登録useraccountsとしてus.userid = u.useridにj.jobid = 123

仕事に参加する回線を切り替えることができます

すべてが会社に加わった場合、どのように見えるでしょう。

SELECT c。*会社からAS cユーザーからユーザーu.companyid = c.companyidに参加ジョブにjとしてj.userid = c.useridに参加useccountsとして私たちとしてus.userid = c.userid WHERE j.jobid = 123

これは実際には意味がありません…​ 各ユーザーが自分の会社を持っていない限り。

4.)SQLの魔法はあなたが唯一の特定の列を表示することができるということですが、それらのすべてはソートとフィルタリングのためのそれらです…​

あなたが戻った場合

SELECT c。*、j.jobid ....

何がフィルタリングされているのかがはっきりとわかりますが、データベースサーバは、行を出力するかどうかを気にしなくてもかまいません。


0


これが `JOIN`優先順位に関するより詳細な答えです。 あなたの場合、 `JOIN`はすべて可換です。 いないところで試してみましょう。

スキーマを構築します。

CREATE TABLE users (
  name text
);

CREATE TABLE orders (
  order_id text,
  user_name text
);

CREATE TABLE shipments (
  order_id text,
  fulfiller text
);

データを追加します。

INSERT INTO users VALUES ('Bob'), ('Mary');

INSERT INTO orders VALUES ('order1', 'Bob');

INSERT INTO shipments VALUES ('order1', 'Fulfilling Mary');

クエリを実行します。

SELECT *
  FROM users
       LEFT OUTER JOIN orders
       ON orders.user_name = users.name
       JOIN shipments
       ON shipments.order_id = orders.order_id

結果:

Bob行のみが返されます

分析:

この問い合わせでは、最初にLEFT OUTER JOINが評価され、JOINがLEFT OUTER JOINの合成結果に対して評価されました。

2番目のクエリ:

SELECT *
  FROM users
       LEFT OUTER JOIN (
         orders
         JOIN shipments
         ON shipments.order_id = orders.order_id)
         ON orders.user_name = users.name

結果:

フルフィルメントデータを含むBob(フルフィルメントデータを含む)およびローリーを含むMaryの1行。

分析:

括弧は評価順序を変更しました。

'' '' '

MySQLの詳細なドキュメントはhttps://dev.mysql.com/doc/refman/5.5/en/nested-join-optimization.htmlにあります。