left join ,right join ,inner join,outer join,union all,union有啥区别?怎么用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了left join ,right join ,inner join,outer join,union all,union有啥区别?怎么用?相关的知识,希望对你有一定的参考价值。

我是数据库菜鸟,希望各位大虾讲的详细些,谢谢。

Table A
aid adate
1 a1
2 a2
3 a3
TableB
bid bdate
1 b1
2 b2
4 b4
两个表a,b相连接,要取出id相同的字段
select * from a inner join b on a.aid = b.bid这是仅取出匹配的数据.
此时的取出的是:
1 a1 b1
2 a2 b2

那么left join 指:
select * from a left join b on a.aid = b.bid
首先取出a表中所有数据,然后再加上与a,b匹配的的数据
此时的取出的是:
1 a1 b1
2 a2 b2
3 a3 空字符

同样的也有right join
指的是首先取出b表中所有数据,然后再加上与a,b匹配的的数据
此时的取出的是:
1 a1 b1
2 a2 b2
4 空字符 b4

LEFT JOIN 或 LEFT OUTER JOIN。
左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值

没什么不同,都一样

只是一种省略的写法就把inner去掉了

不过好像在access中 inner必须要写,否则报错

这个inner就好像as一样,可有可无,如果不写,就默认为是普通连接

union all,解释为联合所有
Union解释为联合
union或者Union all实现把前后两个select集合的数据联合起来,组成一个结果集查询输出。

这就要求联合前后的结果集,需要分别有相同的输出字段的数目,并且对应的字段类型要相同。
SELECT column1, column2 from table1
union (all)
select column1, column2 from table2
以上语句要求量表的column1字段类型相同,column2类型相同。而且每个查询的数目都是一样的。

UNION ALL和UNION的差别就在ALL上面,第一个叫联合所有,说明会显示前后两个查询所有的数据,而UNION没有ALL(所有)这个单词,实现将前后两个查询的数据联合到一起后,去掉重复的数据显示。

比如
SELECT COLUMN1 FROM TABLE1的结果是
1
2
3
SELECT COLUMN1 FROM TABLE2的结果是
1
5
6

分别都是三行,那么UNION ALL的结果就是6行
1
2
3
1
5
6
而UNION会过滤掉上述结果中1的重复一行,结果是
1
2
3
5
6
五行结果
参考技术A jion可以说是一种选择,而union是一种并集,推荐你看一篇文章http://apps.hi.baidu.com/share/detail/46618845追问

还想问一下,如何区分两个表关系是用left join 还是right join ?谢谢您了。

追答

一般表有前后,如果是前一个表连接后一个表,是left join,你看是否是left join,只要看前一个表中的记录是否全部都有,如果有,一般是leftjoin

本回答被提问者采纳

Mysql JOIN with IN 和 RIGHT 表的多个结果

【中文标题】Mysql JOIN with IN 和 RIGHT 表的多个结果【英文标题】:Mysql JOIN with IN and multiple results of RIGHT table 【发布时间】:2012-09-13 04:17:09 【问题描述】:

LEFT 表(简化)是:

id
name (ex:Bob)
tags (ex:1,4,6)

正确的表是:

id
tag (ex:Sailing)

我想像这样得到 LEFT 表的结果:

row 1:
   name: Bob
   tags: Sailing,Snowboard,...

我得到的最近的是那里:

SELECT `name`, GROUP_CONCAT(`right`.`tag`) AS tags
FROM (`left`)
LEFT OUTER JOIN `right` ON `right`.`id` IN(left.tags)
ORDER BY `name` asc

但由于 GROUP_CONCAT(),这只给了我一行。没有它,它给了我所有的结果,但只有逗号分隔列表中的第一个标签。我知道我已经很接近了,但我在这方面浪费了太多时间。任何帮助表示赞赏。

我知道我可以创建第三个表 left_right,其中包含行(id、left_id、right_id)以使其工作,但我想避免这种情况。

【问题讨论】:

tags 是整数字段? (你可以有多个带有不同标签的 Bob 行?) 你无法真正避免这种情况,将来它会变得更加混乱。如果您使用的是关系数据库,请尝试正确使用它们。您需要创建第三个表。 tags 是一个带有逗号分隔数字的 VARCHAR。只有一个“Bob”行包含他的所有标签。我完全同意你的观点,特别是如果我们想在将来从用户中删除标签时让它变得更简单,但是我正在与之一起编写数据库插入编码的另一个人对 mysql 不太好,所以我我试图让他变得简单。 哎哟。然后你想翻译标签从数字到文本?我会编辑我的答案。不过,它变得更加复杂。 是的,我知道,如果太多了,我会帮助我的队友并创建第三张桌子 【参考方案1】:

首先,bažmegakapa 说的是正确的,还有更多。如果我正确理解了您描述的设置,那么您已经在浪费大量空间(和性能)了。

你可以这样做:

CREATE TABLE pleft ( id integer, name varchar(20), tags integer );
CREATE TABLE pright ( id integer, tag varchar(20));

INSERT INTO pleft VALUES ( 1, 'Bob', 1 ), ( 9, 'Bob', 4 ), ( 15, 'Bob', 6 );
INSERT INTO pleft VALUES ( 2, 'Ann', 1 ), ( 3, 'Joe', 4 ), ( 4, 'Joe', 6 );

INSERT INTO pright VALUES ( 1, 'Sailing' ), ( 4, 'Snowboarding' ), ( 6, 'Skiing' );


SELECT pleft.name, GROUP_CONCAT(pright.tag)
    FROM pleft JOIN pright ON ( pleft.tags = pright.id )
    GROUP BY pleft.name ORDER BY pleft.name;

+------+-----------------------------+
| name | GROUP_CONCAT(pright.tag)    |
+------+-----------------------------+
| Ann  | Sailing                     |
| Bob  | Sailing,Skiing,Snowboarding |
| Joe  | Snowboarding,Skiing         |
+------+-----------------------------+

...但请注意名称在pleft 表的每一行中是如何不必要地重复的。理想情况下,您将有一张表对人进行建模:(id=1, name="Bob"),一张表对标签进行建模 (id=6, value="Skiing") 和一张包含它们的关系的表。这将确保,例如,Bob 决定使用“Robert”,您不必对整个标签表进行 de-bob,而只需对涉及 Bob 的一行进行 de-bob。

更新

所以tags 是一个包含“1,4,6”的varchar 字段。同样的逻辑也适用,但现在我们必须在重新组合之前拆分字段。你不能使用像“1 in tags”这样的东西,因为“11”会返回true(“1”毕竟包含在“11”中)。 (这是被称为“乱穿马路”的 SQL 反模式:参见例如 https://groups.google.com/forum/?fromgroups=#!topic/django-users/5j4AmQE6nTk)

SELECT pleft.name, GROUP_CONCAT(pright.tag)
FROM pleft JOIN pright
    ON ( CONCAT(',',pleft.tags,',') LIKE CONCAT('%,',pright.id,',%' ))
GROUP BY pleft.name ORDER BY pleft.name;

另一种方法是使用存储过程:参见http://www.marcogoncalves.com/2011/03/mysql-split-column-string-into-rows/。

CREATE TABLE pleft ( id integer, name varchar(20), tags varchar(20) );
INSERT INTO pleft VALUES ( 1, 'Bob', '1,4,6' ), ( 2, 'Jill', '4,1' );
SELECT pleft.name, GROUP_CONCAT(pright.tag)
    FROM pleft JOIN pright
        ON ( CONCAT(',',pleft.tags,',') LIKE CONCAT('%,',pright.id,',%' ))
    GROUP BY pleft.name ORDER BY pleft.name;
+------+-----------------------------+
| name | GROUP_CONCAT(pright.tag)    |
+------+-----------------------------+
| Bob  | Sailing,Snowboarding,Skiing |
| Jill | Sailing,Snowboarding        |
+------+-----------------------------+

【讨论】:

哇,感谢 Isemi 的提醒,我不知道 MySQL 对 Jaywalkimg 反模式采取了这种方式,这在开发后期会遇到一些麻烦,谢谢!然而,对于包含数十万行的表,使用 LIKE 的解决方法会很慢。如果没有更快的方法,我将创建我的第三个关系表【参考方案2】:

尝试添加一个 GROUP BY 名称字段,您应该能够选择所有名称及其标签的列表。

SELECT `name`, GROUP_CONCAT(`right`.`tag`) AS tags
FROM (`left`)
LEFT OUTER JOIN `right` ON `right`.`id` IN(left.tags)
GROUP BY `name`
ORDER BY `name` ASC;

【讨论】:

不,不工作,无论如何使用 GROUP_BY 是没有意义的,GROUP_CONCAT 查询无论如何只返回一行。

以上是关于left join ,right join ,inner join,outer join,union all,union有啥区别?怎么用?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle left join 或right join

join和left join的区别

求助,left join union right join一直报错

外连接(left join、full join、right join)与内连接(inner join)的区别

sql JOINs - JOIN,INNER JOIN,LEFT JOIN,RIGHT JOIN,CROSS JOIN

left join right inner join 区别