SELECT song_ID,songs.fullname, singers.fullnameFROM music JOIN songs ON songs.ID = music.song_IDJOIN singers ON singers.ID = music.singer_IDGROUP BY songs.fullname
SELECTp.id AS "p.id",pc.id AS "pc.id"FROM post pCROSS JOIN post_commentWHERE 1 = 1ORDER BY p.id, pc.id
SQLINNER JOIN-ON“始终为假”条件
另一方面,如果ON子句条件为“始终为假”,则所有连接的记录都将被过滤掉,结果集将为空。
因此,如果我们执行以下SQLINNER JOIN查询:
SELECTp.id AS "p.id",pc.id AS "pc.id"FROM post pINNER JOIN post_comment pc ON 1 = 0ORDER BY p.id, pc.id
我们不会得到任何结果:
| p.id | pc.id ||---------|------------|
这是因为上面的查询等价于以下CROSS JOIN查询:
SELECTp.id AS "p.id",pc.id AS "pc.id"FROM post pCROSS JOIN post_commentWHERE 1 = 0ORDER BY p.id, pc.id
SQLINNER JOIN-ON子句使用外键和主键列
最常见的ON子句条件是将子表中的外键列与父表中的主键列匹配的条件,如以下查询所示:
SELECTp.id AS "p.id",pc.post_id AS "pc.post_id",pc.id AS "pc.id",p.title AS "p.title",pc.review AS "pc.review"FROM post pINNER JOIN post_comment pc ON pc.post_id = p.idORDER BY p.id, pc.id
SELECTp.id AS "p.id",pc.post_id AS "pc.post_id",pc.id AS "pc.id",p.title AS "p.title",pc.review AS "pc.review"FROM post p, post_comment pcWHERE pc.post_id = p.id
mysql> desc t1;+-------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+-------+| id | int(11) | NO | | NULL | || fid | int(11) | NO | | NULL | || v | varchar(20) | NO | | NULL | |+-------+-------------+------+-----+---------+-------+
这里fid是表t2的id。
mysql> desc t2;+-------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+-------+| id | int(11) | NO | | NULL | || v | varchar(10) | NO | | NULL | |+-------+-------------+------+-----+---------+-------+2 rows in set (0.00 sec)
查询“on条款”:
mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K'-> ;+----+-----+---+------+------+| id | fid | v | id | v |+----+-----+---+------+------+| 1 | 1 | H | NULL | NULL || 2 | 1 | B | NULL | NULL || 3 | 2 | H | NULL | NULL || 4 | 7 | K | NULL | NULL || 5 | 5 | L | NULL | NULL |+----+-----+---+------+------+5 rows in set (0.00 sec)
查询“where子句”:
mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';+----+-----+---+------+------+| id | fid | v | id | v |+----+-----+---+------+------+| 4 | 7 | K | NULL | NULL |+----+-----+---+------+------+1 row in set (0.00 sec)
SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)FROM actor aLEFT JOIN film_actor fa ON a.actor_id = fa.actor_idWHERE film_id < 10GROUP BY a.actor_id, a.first_name, a.last_nameORDER BY count(fa.film_id) ASC;
LEFT JOIN实际上没有任何有用的效果,因为即使演员没有在电影中扮演,演员也会被过滤,因为它的FILM_ID将是NULL,WHERE子句将过滤这样的行。结果类似于:
ACTOR_ID FIRST_NAME LAST_NAME COUNT--------------------------------------194 MERYL ALLEN 1198 MARY KEITEL 130 SANDRA PECK 185 MINNIE ZELLWEGER 1123 JULIANNE DENCH 1
即。就像我们内部连接两个表一样。如果我们移动ON子句中的过滤器谓词,它现在成为外部连接的条件:
SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)FROM actor aLEFT JOIN film_actor fa ON a.actor_id = fa.actor_idAND film_id < 10GROUP BY a.actor_id, a.first_name, a.last_nameORDER BY count(fa.film_id) ASC;
这意味着结果将包含没有任何电影的演员,或者没有任何FILM_ID < 10的电影
ACTOR_ID FIRST_NAME LAST_NAME COUNT-----------------------------------------3 ED CHASE 04 JENNIFER DAVIS 05 JOHNNY LOLLOBRIGIDA 06 BETTE NICHOLSON 0...1 PENELOPE GUINESS 1200 THORA TEMPLE 12 NICK WAHLBERG 1198 MARY KEITEL 1
/ : part of the resultB+---------------------------------+A | |+---------------------+-------+ ||/////////////////////|///////| ||/////////////////////|///////| ||/////////////////////|///////| ||/////////////////////|///////| ||/////////////////////+-------+-------------------------+|/////////////////////////////|+-----------------------------+
在A中但不在B中的内容意味着B有空值。
现在,让我们考虑B.id_A中的一个特定部分,并从上一个结果中突出显示它:
/ : part of the result* : part of the result with the specific B.id_AB+---------------------------------+A | |+---------------------+-------+ ||/////////////////////|///////| ||/////////////////////|///////| ||/////////////////////+---+///| ||/////////////////////|***|///| ||/////////////////////+---+---+-------------------------+|/////////////////////////////|+-----------------------------+
/ : part of the result* : part of the result with the specific B.id_AB+---------------------------------+A | |+---------------------+-------+ ||/////////////////////| | ||/////////////////////| | ||/////////////////////+---+ | ||/////////////////////|***| | ||/////////////////////+---+---+-------------------------+|/////////////////////////////|+-----------------------------+
/ : part of the result* : part of the result with the specific B.id_AB+---------------------------------+A | |+---------------------+-------+ || | | || | | || +---+ | || |***| | || +---+---+-------------------------+| |+-----------------------------+
因为整个结果是根据B.id_A = SpecificPart过滤的,删除了不在B中的A中的B.id_A IS NULL部分
在这种情况下,以前的JOIN ON ... WHERE语法本质上允许您对ID参数进行力主连接操作,仅在主连接完成后对Username进行二次过滤。相比之下,JOIN ON ... AND语法允许优化器选择是在Orders.ID还是Orders.Username上使用索引,理论上它有可能选择最终速度较慢的索引。