Zgodnie z dokumentacją MySQL JOIN w formie:
jest tożsame z zapytaniem w formie:
Sprawdzamy (dane są identyczne jak w przypadku poprzedniego posta):
+-----------------+-----------------+-----------------+-----------------+
| 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:
+-----------------+-----------------+-----------------+-----------------+
| 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:
jest tożsame z zapytaniem:
podczas gdy zapytanie
jest tożsame z zapytaniem:
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:
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+-------------+
| 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.
Komentarze