Join
有时为了得到完整的结果,我们需要从两个或更多的表中获取结果。我们就需要执行 join。
下面列出了您可以使用的 JOIN 类型,以及它们之间的差异。
- JOIN: 如果表中有至少一个匹配,则返回行
- LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
- RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
- FULL JOIN: 只要其中一个表中存在匹配,就返回行
两个字段关联到同一个表,如何使用left join?
其实就是别名,快速理解可以看一下下面这个例子:
SELECT home.id,
t1.name AS one,
t2.name AS two,
t3.name AS three,
t4.name AS four,
t5.name AS five,
t6.name AS six
FROM homepage home
LEFT JOIN commodity_temp t1 ON home.one = t1.uuid
LEFT JOIN commodity_temp t2 ON home.two = t2.uuid
LEFT JOIN commodity_temp t3 ON home.three = t3.uuid
LEFT JOIN commodity_temp t4 ON home.four = t4.uuid
LEFT JOIN commodity_temp t5 ON home.five = t5.uuid
LEFT JOIN commodity_temp t6 ON home.six = t6.uuid
如果上面例子没看懂的话,看这个完整的例子:
示例1:不同表之间的join
-- 账户表
+----+-------+----------+---------+------+
| id | accno | pwd | balance | name |
+----+-------+----------+---------+------+
| 1 | 10001 | zhangsan | 1124.13 | 张三 |
| 2 | 10002 | lisi | 1537.42 | 李四 |
| 3 | 10003 | wangwu | 2956.58 | 王五 |
| 4 | 10004 | laoda | 4381.87 | 老大 |
+----+-------+----------+---------+------+
-- 转账记录
+----+--------+-------+--------+----------------------+
| id | accout | accin | money | reason |
+----+--------+-------+--------+----------------------+
| 1 | 10002 | 10001 | 100 | 货到付款 |
| 2 | 10001 | 10002 | 5 | 买橘子 |
| 3 | 10001 | 10003 | 1 | NULL |
| 4 | 10004 | 10002 | 66 | NULL |
| 5 | 10002 | 10004 | 55 | NULL |
| 6 | 10003 | 10004 | 70 | NULL |
| 7 | 10001 | 10004 | 5 | NULL |
| 8 | 10002 | 10001 | 5 | 捡到五块钱,上交 |
| 9 | 10001 | 10003 | 2 | NULL |
| 10 | 10003 | 10001 | 3 | 发财了 |
| 11 | 10002 | 10002 | 15 | NULL |
| 12 | 10001 | 10001 | 100 | 自己给自己打钱 |
| 13 | 10004 | 10003 | 26.58 | NULL |
| 14 | 10001 | 10002 | 11.76 | 利息 |
| 15 | 10002 | 10004 | 500 | 捡了500块,交给老大 |
| 16 | 10004 | 10001 | 255.55 | 张三盗取了老大的账号 |
| 17 | 10002 | 10001 | 80.45 | 张三买了个橘子 |
| 18 | 10002 | 10001 | 4.89 | 李四向张三还款 |
| 19 | 10002 | 10004 | 100 | 老大没钱了 |
+----+--------+-------+--------+----------------------+
-- 想要达到的效果:如下,在转账记录的accin和accout列旁边分别加一列,显示对应账户的name
select log.id,
accout,
a1.name,
log.accin,
a2.name,
money,
reason
FROM log
left join account a1 on log.accout = a1.accno
left join account a2 on log.accin = a2.accno;
+----+--------+------+-------+------+--------+----------------------+
| id | accout | name | accin | name | money | reason |
+----+--------+------+-------+------+--------+----------------------+
| 1 | 10002 | 李四 | 10001 | 张三 | 100 | 货到付款 |
| 2 | 10001 | 张三 | 10002 | 李四 | 5 | 买橘子 |
| 3 | 10001 | 张三 | 10003 | 王五 | 1 | NULL |
| 4 | 10004 | 老大 | 10002 | 李四 | 66 | NULL |
| 5 | 10002 | 李四 | 10004 | 老大 | 55 | NULL |
| 6 | 10003 | 王五 | 10004 | 老大 | 70 | NULL |
| 7 | 10001 | 张三 | 10004 | 老大 | 5 | NULL |
| 8 | 10002 | 李四 | 10001 | 张三 | 5 | 捡到五块钱,上交 |
| 9 | 10001 | 张三 | 10003 | 王五 | 2 | NULL |
| 10 | 10003 | 王五 | 10001 | 张三 | 3 | 发财了 |
| 11 | 10002 | 李四 | 10002 | 李四 | 15 | NULL |
| 12 | 10001 | 张三 | 10001 | 张三 | 100 | 自己给自己打钱 |
| 13 | 10004 | 老大 | 10003 | 王五 | 26.58 | NULL |
| 14 | 10001 | 张三 | 10002 | 李四 | 11.76 | 利息 |
| 15 | 10002 | 李四 | 10004 | 老大 | 500 | 捡了500块,交给老大 |
| 16 | 10004 | 老大 | 10001 | 张三 | 255.55 | 张三盗取了老大的账号 |
| 17 | 10002 | 李四 | 10001 | 张三 | 80.45 | 张三买了个橘子 |
| 18 | 10002 | 李四 | 10001 | 张三 | 4.89 | 李四向张三还款 |
| 19 | 10002 | 李四 | 10004 | 老大 | 100 | 老大没钱了 |
+----+--------+------+-------+------+--------+----------------------+
示例2:同一张表本身的join
查询特定父节点下的子节点,并将父节点的名称显示出来。
SELECT basic_menu.`id`, basic_menu.`name`, basic_menu.`pid`, basic_menu.`url`, basic_menu.`p_code`, b1.name AS chn_name
FROM `basic_menu`
JOIN basic_menu b1 ON basic_menu.pid=b1.id
WHERE basic_menu.pid IN
(SELECT basic_menu.id FROM `basic_menu` WHERE basic_menu.`name` LIKE '%库存%' AND basic_menu.`name`!='库存')
AND basic_menu.`name` LIKE '%年份%'