mysql怎么五mysql两个表联合查询询

6.MySql中的SQL语句(五):多表查询 - 简书
6.MySql中的SQL语句(五):多表查询
多表查询有如下几种:合并结果集;UNION、UNION ALL连接查询内连接[INNER] JOINON外连接OUTER JOIN ON左外连接LEFT [OUTER] JOIN右外连接RIGHT [OUTER] JOIN全外连接(MySQL不支持)FULL JOIN自然连接NATURAL JOIN子查询合并结果集1.作用:合并结果集就是把两个select语句的查询结果合并到一起!2.合并结果集有两种方式:UNION:去除重复记录,例如:SELECT FROM t1 UNION SELECT * FROM t2;UNION ALL:不去除重复记录,例如:SELECT * FROM t1 UNION ALL SELECT * FROM t2。
要求:被合并的两个结果:列数、列类型必须相同。连接查询连接查询就是求出多个表的乘积,例如t1连接t2,那么查询出的结果就是t1*t2。
连接查询会产生笛卡尔积,假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况。那么多表查询产生这样的结果并不是我们想要的,那么怎么去除重复的,不想要的记录呢,当然是通过条件过滤。通常要查询的多个表之间都存在关联关系,那么就通过关联关系去除笛卡尔积。你能想像到emp和dept表连接查询的结果么?emp一共14行记录,dept表一共4行记录,那么连接后查询出的结果是56行记录。也就你只是想在查询emp表的同时,把每个员工的所在部门信息显示出来,那么就需要使用主外键来去除无用信息了。
使用主外键关系做为条件来去除无用信息SELECT * FROM emp,dept WHERE;在多表查询中,在使用列时必须指定列所从属的表,例如emp.deptno表示emp表的deptno列。
上面查询结果会把两张表的所有列都查询出来,也许你不需要那么多列,这时就可以指定要查询的列了。
SELECTemp.ename,emp.m,dept.dnameFROM emp,deptWHERE emp.deptno=dept.
还可以为表指定别名,然后在引用列时使用别名即可。FROMemp AS e,dept AS dWHEREe.deptno=d.其中AS是可以省略的内连接上面的连接语句就是内连接,但它不是SQL标准中的查询方式,可以理解为方言!SQL标准的内连接为:SELECT *FROM emp eJOIN dept de.deptno=d.内连接的特点:查询结果必须满足条件。例如我们向emp表中插入一条记录:其中deptno为50,而在dept表中只有10、20、30、40部门,那么上面的查询结果中就不会出现“张三”这条记录,因为它不能满足e.deptno=d.deptno这个条件。2.2外连接(左连接、右连接)外连接的特点:查询出的结果存在不满足条件的可能。左连接:SELECT * FROM emp eLEFT OUTERJOIN dept dON e.deptno=d.左连接是先查询出左表(即以左表为主),然后查询右表,右表中满足条件的显示出来,不满足条件的显示NULL。这么说你可能不太明白,我们还是用上面的例子来说明。其中emp表中“张三”这条记录中,部门编号为50,而dept表中不存在部门编号为50的记录,所以“张三”这条记录,不能满足e.deptno=d.deptno这条件。但在左连接中,因为emp表是左表,所以左表中的记录都会查询出来,即“张三”这条记录也会查出,但相应的右表部分显示NULL。INNER可以省略,MySQL默认的连接方式就是内连接不使用WHERE,而是使用ONOUTER可以省略
右连接右连接就是先把右表中所有记录都查询出来,然后左表满足条件的显示,不满足显示NULL。例如在dept表中的40部门并不存在员工,但在右连接中,如果dept表为右表,那么还是会查出40部门,但相应的员工信息为NULL。SELECT * FROM emp eRIGHT OUTER JOIN dept dON e.deptno=d.
自然连接大家也都知道,连接查询会产生无用笛卡尔积,我们通常使用主外键关系等式来去除它。而自然连接无需你去给出主外键等式,它会自动找到这一等式:l两张连接的表中名称和类型完全一致的列作为条件,例如emp和dept表都存在deptno列,并且类型一致,所以会被自然连接找到!当然自然连接还有其他的查找条件的方式,但其他方式都可能存在问题!SELECT * FROM emp NATURAL JOINSELECT * FROM emp NATURAL LEFT JOINSELECT * FROM emp NATURAL RIGHT JOIN子查询一个select语句中包含另一个完整的select语句。子查询就是嵌套查询,即SELECT中包含SELECT,如果一条语句中存在两个,或两个以上SELECT,那么就是子查询语句了。子查询出现的位置:where后,作为条为被查询的一条件的一部分;from后,作表;当子查询出现在where后作为条件时,还可以使用如下关键字:anyall子查询结果集的形式:单行单列(用于条件)单行多列(用于条件)多行单列(用于条件)多行多列(用于表)练习:1.工资高于JONES的员工。分析:查询条件:工资&JONES工资,其中JONES工资需要一条子查询。第一步:查询JONES的工资SELECT sal FROM emp WHERE ename='JONES'第二步:查询高于甘宁工资的员工SELECT * FROM emp WHERE sal & (${第一步})结果:SELECT * FROM emp WHERE sal & (SELECTsal FROM emp WHERE ename='JONES')2、查询与SCOTT同一个部门的员工。l子查询作为条件l子查询形式为单行单列3、工资高于30号部门所有人的员工信息分析:SELECT * FROMemp WHERE sal&(SELECT MAX(sal)FROM emp WHERE deptno=30);查询条件:工资高于30部门所有人工资,其中30部门所有人工资是子查询。高于所有需要使用all关键字。第一步:查询30部门所有人工资SELECT sal FROM emp WHERE deptno=30;第二步:查询高于30部门所有人工资的员工信息SELECT * FROM emp WHERE sal & ALL (${第一步})结果:SELECT * FROM emp WHERE sal &(SELECT sal FROM empWHERE deptno=30)l子查询作为条件l子查询形式为多行单列(当子查询结果集形式为多行单列时可以使用ALL或ANY关键字)4、查询工作和工资与MARTIN(马丁)完全相同的员工信息分析:查询条件:工作和工资与MARTIN完全相同,这是子查询第一步:查询出MARTIN的工作和工资SELECT job,sal FROM emp WHEREename='MARTIN'第二步:查询出与MARTIN工作和工资相同的人SELECT * FROM emp WHERE (job,sal) IN (${第一步})结果:SELECT * FROM emp WHERE (job,sal) IN(SELECT job,sal FROM emp WHERE ename='MARTIN')5、有2个以上直接下属的员工信息SELECT * FROMemp WHERE empno IN(SELECT mgr FROMemp GROUP BY mgr HAVING COUNT(mgr)&=2);l子查询作为条件l子查询形式为单行多列5、查询员工编号为7788的员工名称、员工工资、部门名称、部门地址分析:(无需子查询)查询列:员工名称、员工工资、部门名称、部门地址查询表:emp和dept,分析得出,不需要外连接(外连接的特性:某一行(或某些行)记录上会出现一半有值,一半为NULL值)条件:员工编号为7788第一步:去除多表,只查一张表,这里去除部门表,只查员工表SELECT ename, sal FROM emp e WHERE empno=7788第二步:让第一步与dept做内连接查询,添加主外键条件去除无用笛卡尔积SELECT e.ename, e.sal, d.dname, d.locFROM emp e, dept dWHERE e.deptno=d.deptno AND empno=7788第二步中的dept表表示所有行所有列的一张完整的表,这里可以把dept替换成所有行,但只有dname和loc列的表,这需要子查询。第三步:查询dept表中dname和loc两列,因为deptno会被作为条件,用来去除无用笛卡尔积,所以需要查询它。SELECT dname,loc,deptno FROM第四步:替换第二步中的deptSELECT e.ename, e.sal, d.dname, d.locFROM emp e, (SELECT dname,loc,deptno FROMdept) dWHERE e.deptno=d.deptno AND e.empno=7788子查询作为表l子查询形式为多行多列6、自连接:自己连接自己,起别名求7369员工编号、姓名、经理编号和经理姓名SELECT e1.empno , e1.ename,e2.mgr,e2.enameFROMemp e1, emp e2WHEREe1.mgr = e2.empno AND e1.empno = 7369;练习:求各个部门薪水最高的员工所有信息select e.* from emp e,--部门最高工资(select max(sal) maxsal,deptno from empgroup by deptno) awhere e.deptno = a.deptnoand e.sal =a.maxsal
无偿分享本人掌握的所有技术!188141人阅读
MySQL(11)
1. 笛卡尔积(交叉连接) 在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者使用','& 如:&
SELECT * FROM table1 CROSS JOIN table2
SELECT * FROM table1 JOIN table2
SELECT * FROM table1,table2
&&&&&&& 由于其返回的结果为被连接的两个数据表的乘积,因此当有WHERE, ON或USING条件的时候一般不建议使用,因为当数据表项目太多的时候,会非常慢。一般使用LEFT [OUTER] JOIN或者RIGHT [OUTER] JOIN
&2.&&&内连接INNER JOIN 在MySQL中把INNER JOIN叫做等值连接,即需要指定等值连接条件在MySQL中CROSS和INNER JOIN被划分在一起。 join_table: table_reference [INNER | CROSS] JOIN table_factor [join_condition]
3. MySQL中的外连接,分为左外连接和右连接,即除了返回符合连接条件的结果之外,还要返回左表(左连接)或者右表(右连接)中不符合连接条件的结果,相对应的使用NULL对应。
3 | daodao
user_action表:
user_id | action
—————
select id, name, action from user as u
left join user_action a on u.id = a.user_id
id | name&&& | action
——————————–
1& | libk&& &&&&& | jump&&&&&&&&&& ①
1& | libk&&&&&&& &| kick&&&&&& &&&&& ②
1 &| libk&& &&&&& | jump&&&&&&&&& &③
2 &| zyfon&&&& &| run&&&&&&&&& &&&& ④
3& | daodao | null&&&&&&&&&&&&& ⑤
注意到user_action中还有一个user_id=4, action=swim的纪录,但是没有在结果中出现,
而user表中的id=3, name=daodao的用户在user_action中没有相应的纪录,但是却出现在了结果集中
因为现在是left join,所有的工作以left为准.
结果1,2,3,4都是既在左表又在右表的纪录,5是只在左表,不在右表的纪录
工作原理:
从左表读出一条,选出所有与on匹配的右表纪录(n条)进行连接,形成n条纪录(包括重复的行,如:结果1和结果3),如果右边没有与on条件匹配的表,那连接的字段都是null.然后继续读下一条。
我们可以用右表没有on匹配则显示null的规律, 来找出所有在左表,不在右表的纪录, 注意用来判断的那列必须声明为not null的。
select id, name, action from user as u
left join user_action a on u.id = a.user_id
where a.user_id is NULL
&&&&&&& 1.列值为null应该用is null 而不能用=NULL
&&&&&&&&&2.这里a.user_id 列必须声明为 NOT NULL 的.
上面sql的result:
id | name | action
————————–
3 | daodao | NULL
——————————————————————————–
一般用法:
a. LEFT [OUTER] JOIN:
除了返回符合连接条件的结果之外,还需要显示左表中不符合连接条件的数据列,相对应使用NULL对应
SELECT column_name FROM table1 LEFT [OUTER] JOIN table2 ON table1.column=table2.column
b. RIGHT [OUTER] JOIN:
RIGHT与LEFT JOIN相似不同的仅仅是除了显示符合连接条件的结果之外,还需要显示右表中不符合连接条件的数据列,相应使用NULL对应
SELECT column_name FROM table1 RIGHT [OUTER] JOIN table2 ON table1.column=table2.column
1. on a.c1 = b.c1 等同于 using(c1)
2. INNER JOIN 和 , (逗号) 在语义上是等同的
3. 当 MySQL 在从一个表中检索信息时,你可以提示它选择了哪一个索引。
如果 EXPLAIN 显示 MySQL 使用了可能的索引列表中错误的索引,这个特性将是很有用的。
通过指定 USE INDEX (key_list),你可以告诉 MySQL 使用可能的索引中最合适的一个索引在表中查找记录行。
可选的二选一句法 IGNORE INDEX (key_list) 可被用于告诉 MySQL 不使用特定的索引。如:
mysql& SELECT * FROM table1 USE INDEX (key1,key2)
-& WHERE key1=1 AND key2=2 AND key3=3;
mysql& SELECT * FROM table1 IGNORE INDEX (key3)
-& WHERE key1=1 AND key2=2 AND key3=3;
&添加显示条件WHERE, ON, USING
1. WHERE子句
SELECT * FROM table1,table2 WHERE table1.id=table2.
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
LEFT JOIN table3 ON table2.id=table3.
3. USING子句,如果连接的两个表连接条件的两个列具有相同的名字的话可以使用USING
SELECT FROM LEFT JOIN USING ()
连接多于两个表的情况举例:
SELECT artists.Artist, cds.title, genres.genre
LEFT JOIN genres N cds.genreID = genres.genreID
LEFT JOIN artists ON cds.artistID = artists.artistID;
或者 mysql&
SELECT artists.Artist, cds.title, genres.genre
LEFT JOIN genres ON cds.genreID = genres.genreID
LEFT JOIN artists -& ON cds.artistID = artists.artistID
WHERE (genres.genre = 'Pop');
--------------------------------------------
&另外需要注意的地方 在MySQL中涉及到多表查询的时候,需要根据查询的情况,想好使用哪种连接方式效率更高。
&1. 交叉连接(笛卡尔积)或者内连接 [INNER | CROSS] JOIN
&2. 左外连接LEFT [OUTER] JOIN或者右外连接RIGHT [OUTER] JOIN 注意指定连接条件WHERE, ON,USING.
在MySQL中,A LEFT JOIN B join_condition执行过程如下:
1)·& 根据表A和A依赖的所有表设置表B。
2)·&&根据LEFT JOIN条件中使用的所有表(除了B)设置表A。
3)·&&&LEFT JOIN条件用于确定如何从表B搜索行。(换句话说,不使用WHERE子句中的任何条件)。
4)·& 可以对所有标准联接进行优化,只是只有从它所依赖的所有表读取的表例外。如果出现循环依赖关系,MySQL提示出现一个错误。
5)· 进行所有标准WHERE优化。
6)· 如果A中有一行匹配WHERE子句,但B中没有一行匹配ON条件,则生成另一个B行,其中所有列设置为NULL。
7)· 如果使用LEFT JOIN找出在某些表中不存在的行,并且进行了下面的测试:WHERE部分的col_name IS NULL,其中col_name是一个声明为 NOT NULL的列,MySQL找到匹配LEFT JOIN条件的一个行后停止(为具体的关键字组合)搜索其它行。
RIGHT JOIN的执行类似LEFT JOIN,只是表的角色反过来。
联接优化器计算表应联接的顺序。LEFT JOIN和STRAIGHT_JOIN强制的表读顺序可以帮助联接优化器更快地工作,因为检查的表交换更少。请注意这说明如果执行下面类型的查询,MySQL进行全扫描b,因为LEFT JOIN强制它在d之前读取:
FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key)
WHERE b.key=d.
在这种情况下修复时用a的相反顺序,b列于FROM子句中:
FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d ON (d.key=a.key)
WHERE b.key=d.
MySQL可以进行下面的LEFT JOIN优化:如果对于产生的NULL行,WHERE条件总为假,LEFT JOIN变为普通联接。
例如,在下面的查询中如果t2.column1为NULL,WHERE 子句将为false:
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;
因此,可以安全地将查询转换为普通联接:
SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;
这样可以更快,因为如果可以使查询更佳,MySQL可以在表t1之前使用表t2。为了强制使用表顺序,使用STRAIGHT_JOIN。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:5709680次
积分:30152
积分:30152
排名:第148名
原创:217篇
评论:1444条
扫码打赏,你说多少就多少
(1)(1)(2)(3)(2)(4)(2)(1)(2)(1)(1)(2)(1)(1)(1)(1)(1)(2)(2)(1)(2)(3)(3)(2)(2)(2)(4)(3)(2)(15)(6)(8)(14)(29)(26)(27)(18)(7)(8)(6)(2)

我要回帖

更多关于 mysql 3表联合查询 的文章

 

随机推荐