Zgodnie z dokumentacją MySQL JOIN w formie:

SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1;

jest tożsame z zapytaniem w formie:

SELECT kol11, kol12, kol21, kol22 FROM tab1 JOIN tab2 USING (id_1) JOIN tab3 USING (id_1);

Sprawdzamy (dane są identyczne jak w przypadku poprzedniego posta):

mysql> SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1;
+-----------------+-----------------+-----------------+-----------------+
| kol11           | kol12           | kol21           | kol22           |
+-----------------+-----------------+-----------------+-----------------+
| dcydbdbzdydazcz | cyzycdbcybzdczy | bcdybzdbczbcbzy | bdcybydybybyzcb |
| cbydydyaydcbzby | ydyzbdcdbyczbyd | cbcybdczbcbzyzd | dbzdcbzbdybdydz |
+-----------------+-----------------+-----------------+-----------------+
2 rows in set (0.00 sec)

mysql> SELECT kol11, kol12, kol21, kol22 FROM tab1 JOIN tab2 USING (id_1) JOIN tab3 USING (id_1);
+-----------------+-----------------+-----------------+-----------------+
| kol11           | kol12           | kol21           | kol22           |
+-----------------+-----------------+-----------------+-----------------+
| dcydbdbzdydazcz | cyzycdbcybzdczy | bcdybzdbczbcbzy | bdcybydybybyzcb |
| cbydydyaydcbzby | ydyzbdcdbyczbyd | cbcybdczbcbzyzd | dbzdcbzbdybdydz |
+-----------------+-----------------+-----------------+-----------------+
2 rows in set (0.00 sec)

W tym wypadku praktyka zgadza się z dokumentacją (co prawda, w przypadku zapytania typu SELECT * różnica już by wystąpiła, ale to opowieść na inny raz). Dorzućmy do tego jakieś warunki:

mysql> SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1 AND kol21 NOT LIKE 'b%' OR kol12 LIKE 'c%';
+-----------------+-----------------+-----------------+-----------------+
| kol11           | kol12           | kol21           | kol22           |
+-----------------+-----------------+-----------------+-----------------+
| dcydbdbzdydazcz | cyzycdbcybzdczy | bcdybzdbczbcbzy | bdcybydybybyzcb |
| dcydbdbzdydazcz | cyzycdbcybzdczy | cbcybdczbcbzyzd | dbzdcbzbdybdydz |
| dcydbdbzdydazcz | cyzycdbcybzdczy | bcdybzdbczbcbzy | bdcybydybybyzcb |
| dcydbdbzdydazcz | cyzycdbcybzdczy | cbcybdczbcbzyzd | dbzdcbzbdybdydz |
| cbydydyaydcbzby | ydyzbdcdbyczbyd | cbcybdczbcbzyzd | dbzdcbzbdybdydz |
+-----------------+-----------------+-----------------+-----------------+
5 rows in set (0.00 sec)

mysql> SELECT kol11, kol12, kol21, kol22 FROM tab1 JOIN tab2 USING (id_1) JOIN tab3 USING (id_1) WHERE kol21 NOT LIKE 'b%' OR kol12 LIKE 'c%';
+-----------------+-----------------+-----------------+-----------------+
| kol11           | kol12           | kol21           | kol22           |
+-----------------+-----------------+-----------------+-----------------+
| dcydbdbzdydazcz | cyzycdbcybzdczy | bcdybzdbczbcbzy | bdcybydybybyzcb |
| cbydydyaydcbzby | ydyzbdcdbyczbyd | cbcybdczbcbzyzd | dbzdcbzbdybdydz |
+-----------------+-----------------+-----------------+-----------------+
2 rows in set (0.00 sec)

Coś jest nie tak, wyniki się różnią. Gdzie leży problem? Problem leży tu.
Operator AND ma wyższy priorytet niż operator OR. W efekcie zapytanie:

SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1 AND kol21 NOT LIKE 'b%' OR kol12 LIKE 'c%';

jest tożsame z zapytaniem:

SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE (tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1 AND kol21 NOT LIKE 'b%') OR (kol12 LIKE 'c%');

podczas gdy zapytanie

SELECT kol11, kol12, kol21, kol22 FROM tab1 JOIN tab2 USING (id_1) JOIN tab3 USING (id_1) WHERE kol21 NOT LIKE 'b%' OR kol12 LIKE 'c%';

jest tożsame z zapytaniem:

SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE (tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1) AND (kol21 NOT LIKE 'b%' OR kol12 LIKE 'c%');

Różnice są w umiejscowieniu nawiasów. Jeśli JOIN pisany jest przy pomocy warunków WHERE, dobrze jest zwrócić szczególną uwagę na kolejność porównywanych warunków. Szczególnie, że brak nawiasu może spowodować ogromną różnicę w wydajności:

mysql> EXPLAIN SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE (tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1) AND (kol21 NOT LIKE 'b%' OR kol12 LIKE 'c%');
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref            | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+-------------+
|  1 | SIMPLE      | tab1  | ALL    | PRIMARY       | NULL    | NULL    | NULL           |    2 |             |
|  1 | SIMPLE      | tab2  | eq_ref | PRIMARY       | PRIMARY | 4       | test.tab1.id_1 |    1 | Using where |
|  1 | SIMPLE      | tab3  | eq_ref | PRIMARY       | PRIMARY | 4       | test.tab1.id_1 |    1 | Using index |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+-------------+
3 rows in set (0.00 sec)

mysql> EXPLAIN SELECT kol11, kol12, kol21, kol22 FROM tab1, tab2, tab3 WHERE tab1.id_1 = tab2.id_1 AND tab1.id_1 = tab3.id_1 AND kol21 NOT LIKE 'b%' OR kol12 LIKE 'c%';
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+
|  1 | SIMPLE      | tab1  | ALL   | PRIMARY       | NULL    | NULL    | NULL |    2 |                                             |
|  1 | SIMPLE      | tab2  | ALL   | PRIMARY       | NULL    | NULL    | NULL |    2 | Using where; Using join buffer              |
|  1 | SIMPLE      | tab3  | index | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where; Using index; Using join buffer |
+----+-------------+-------+-------+---------------+---------+---------+------+------+---------------------------------------------+
3 rows in set (0.00 sec)

Widać, że jesteśmy w punkcie opisanym w poprzednim poście – generowana jest kombinacja wszystkich rekordów i dopiero na to nakładane są dodatkowe warunki.