0

結合に関して本当に混乱することを尋ねる必要があります

私が思うことと、これは過去に私のために働いていたと確信していますが、何かが欠けているようです:

このクエリは、client_id が 1 である両方のテーブルからのデータを生成します - 正常に動作しています

/* gets data for one client_id*/

approach 1A

SELECT * 
FROM clients  LEFT JOIN client_modules 
                ON client_modules.client_id = clients.client_id
WHERE clients.client_id = 1;

さて、このクエリは同じ結果を返すはずだと思います。結合でサブクエリを使用して最初に結果をフィルタリングしたためです。すでに client_id 1 のモジュールからデータを取得していますが、何らかの理由で最終結果に他の client_ids データを与えています。

/* gets data for one client_id sub-query approach*/

approach 2A

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
                        FROM client_modules 
                        WHERE client_modules.client_id = 1) 
             AS client_moduless ON client_moduless.client_id = clients.client_id;



/* gets data for all client_ids */

approach 1B

SELECT * FROM clients
LEFT JOIN client_modules ON client_modules.client_id = clients.client_id;



/* gets data for all client_ids*/

approach 2B

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
                        FROM client_modules) AS client_moduless
              ON client_moduless.client_id = clients.client_id;

質問:

1) 大量のデータを使用する場合、どのアプローチがより効率的xA and xBですか?

2) サブクエリを join で個別に実行しても問題なく動作するのに、2 番目のアプローチ2Aで結果が得られるのはなぜですか?client_ids other then 1

3) 2Bwhere句を使用しない場合、親からのすべてのレコードに対してサブクエリが実行されますか?

4) 1A クエリを次のように変更するとどうなりますか?

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id AND client_modules.client_id = 1

クライアントテーブルのwhere句を削除し、子テーブルの結合句にこれを効率的またはwhere句に入れましたか?

よろしく

4

2 に答える 2

1

2a は、左結合を使用したため、余分なクライアントをプルします。つまり、左側からはすべてのレコードが、右側からは関連するレコードのみがプルされます。「左結合」ではなく、「完全結合」または「結合」を使用する必要があります。

他の質問についてはわかりませんが、私の好みはサブセレクトよりも1Bです

編集して追加 - 左結合で何が起こっているのかを理解するために、その多くの用途の 1 つを検討してください - client_modules にレコードがないクライアントはどれですか?

次のように書きたくなります。

SELECT * FROM clients WHERE clientid NOT IN (select distinct(clientid) FROM client_modules)

ただし、次のように書くとおそらくより効率的です。

SELECT * FROM clients
     LEFT JOIN  client_modules ON clients.clientid = client_modules.clientid
WHERE client_modules.clientid IS NULL

(つまり、 client_module 行に結合できないクライアントからのレコードのみを表示します)

于 2012-05-16T09:01:24.973 に答える
1

いいえ。私の考えでは、を使用すべきではないと思いますleft join。を使用する必要がありますjoin。万力のように:

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id
WHERE clients.client_id = 1;

LEFT JOINこれはより単純であり、where ステートメントでを制限しているため、同じ効果があります。

SELECT * 
FROM clients LEFT JOIN (SELECT client_id, module_name 
                        FROM client_modules 
                        WHERE client_modules.client_id = 1) 
             AS client_moduless ON client_moduless.client_id = clients.client_id;

このクエリを使用すると、client テーブル内のすべての行が返され、client_moduless.client_id = clients.client_id に一致する行については、そのテーブルが作成されます。しかし、これは制限JOINではなく、左結合であるため、値が一致しない場合はnullが返されます。サブクエリはすべての行に対して実行されます。同じ効果を得るには、次のようにします。

SELECT * 
FROM clients JOIN (SELECT client_id, module_name 
                        FROM client_modules 
                        WHERE client_modules.client_id = 1) 
             AS client_moduless ON client_moduless.client_id = clients.client_id;

clientsこれでテーブルが制限され、 で一致する値のみが取得されclient_modulesます。しかし、それを行うポイントがわかりません。代わりに海峡を進みjoinます。

また、何に関心があるかによっても異なります。クライアント テーブルの列だけにいる場合。次に、これを行うことができます:

SELECT * 
FROM clients
WHERE EXISTS
(
    SELECT 
        NULL
    FROM
        client_modules=1
        AND client_moduless.client_id = clients.client_id
)

したがって、clientsテーブルのすべての列が必要な場合client_modulesは、結合を使用します。それ以外の場合は、exists

編集

私はこう思います:

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id 
AND client_modules.client_id = 1

この:

SELECT * FROM clients
JOIN client_modules ON client_modules.client_id = clients.client_id
WHERE client_modules.client_id = 1

同じです。これにより、ほとんどの場合、同じクエリ プランが得られます。

于 2012-05-16T09:01:38.360 に答える