站长工具seo综合查询引流网站建设一般花多少费用
多表联合查询
在关系型数据库中,表与表之间是有联系的,所以在实际应用中,经常使用多表查询。多表查询就是同时查询两个或两个以上的表。 在MySQL中,多表查询主要有交叉连接、内连接、外连接、分组查询与子查询等5种。
一、交叉连接(cross join)
交叉连接有两种:显式和隐式的2种,一般用来返回连接表的笛卡尔积。 笛卡尔积(Cartesian product)是指两个集合 X 和 Y 的乘积。 多表查询遵循的算法就是以上提到的笛卡尔积,表与表之间的连接可以看成是在做乘法运算。在实际应用中,应避免使用笛卡尔积,因为笛卡尔积中容易存在大量的不合理数据,简单来说就是容易导致查询结果重复、混乱。
--语法格式:select 字段名 from 表1 cross join 表2 ... cross join 表n [where子句];--或者select 字段名 from 表1,表2,...,表n [where子句];/*字段名:需要查询的字段名称。表1,表2,...,表n:需要交叉连接的表名。where 子句:用来设置交叉连接的查询条件。*/
当连接的表之间没有关系时,会省略掉where子句,这时返回结果就是两个表的笛卡尔积,返回结果数量就是两个表的数据行相乘。当两个表的数据行很多时,数据量是非常巨大的。 交叉连接一般用于对数据库进行压力测试。
案例:
查询course表中的id字段和student123表中的course_id字段相等的内容
select * from course cross join student123where course.id=student123.course_id;
+----+-------------+----+--------+------+-------+--------+-----------+| id | course_name | id | name | age | sex | height | course_id |+----+-------------+----+--------+------+-------+--------+-----------+| 1 | Java | 1 | Dany | 25 | man | 160 | 1 || 2 | MySQL | 2 | Green | 23 | man | 158 | 2 || 1 | Java | 3 | Henry | 23 | woman | 185 | 1 || 3 | Python | 4 | Jane | 22 | man | 162 | 3 || 2 | MySQL | 5 | Jim | 24 | woman | 175 | 2 || 4 | Go | 6 | John | 21 | woman | 172 | 4 || 4 | Go | 7 | Lily | 32 | man | 165 | 4 || 5 | C++ | 8 | Susan | 23 | man | 170 | 5 || 5 | C++ | 9 | Thomas | 22 | woman | 178 | 5 || 5 | C++ | 10 | Tom | 23 | woman | 165 | 5 |+----+-------------+----+--------+------+-------+--------+-----------+
如果在交叉连接时使用 WHERE 子句,MySQL 会先生成两个表的笛卡尔积,然后再选择满足 WHERE 条件的记录。因此,表的数量较多时,交叉连接会非常非常慢。一般情况下不建议使用交叉连接。 在 MySQL 中,多表查询一般使用内连接和外连接,它们的效率要高于交叉连接。
二、内连接(inner join)
内连接主要通过设置连接条件的方式,来移除查询结果中某些数据行的交叉连接。简单来说,就是利用条件表达式来消除交叉连接的某些数据行。 内连接使用inner join关键字连接两张表,并使用on子句来设置连接条件。如果没有连接条件,inner join和cross join在语法上是等同的,两者可以互换。
---语法格式:select 字段名 from 表1 inner join 表2 ... inner join 表n [on子句];/*字段名:需要查询的字段名称。表1,表2,...表n:需要内连接的表名。inner join:内连接中可以省略 inner 关键字,只用关键字 join。on子句:用来设置内连接的连接条件。*/
inner join也可以使用where子句指定连接条件,但是inner join...on语法是官方的标准写法,而且where子句在某些时候会影响查询的性能。
案例:使用内连接查询学生姓名和相对应的课程名称
select student123.name,course.course_name from student123 join course on student123.course_id=course.id;
+--------+-------------+| name | course_name |+--------+-------------+| Dany | Java || Green | MySQL || Henry | Java || Jane | Python || Jim | MySQL || John | Go || Lily | Go || Susan | C++ || Thomas | C++ || Tom | C++ |+--------+-------------+
三、外连接
内连接的查询结果都是符合连接条件的记录,而外连接会先将连接的表分为基表和参考表,再以基表为依据返回满足和不满足条件的记录。 外连接可以分为左外连接与右外连接两种。
1、左外连接
左外连接又称为左连接,使用left outer join关键字连接两个表,并使用on子句来设置连接条件。
--语法格式:select 字段名 from 表1 left out er join 表2 on子句;/*left outer join中可以省略outer关键字,只是用关键字left joinon子句:用来设置左连接的连接条件,不能省略上述语法中,表1为基表,表2为参考表。查询时可以查询出表1中的所有记录行和biao2中匹配连接条件的记录。如果表1的某行再表2中没有匹配行,那么返回结果中,表2的字段值均为空值(NULL)*/
案例:
在student123表和course表中查询所有学生姓名和相对应的课程名称,包括没有课程的学生
select student123.name,course.course_name from student123 left join course on student123.course_id=course.id;
+--------+-------------+ | name | course_name | +--------+-------------+ | Dany | Java | | Henry | Java | | Green | MySQL | | Jim | MySQL | | Jane | Python | | John | Go | | Lily | Go | | Susan | C++ | | Thomas | C++ | | Tom | C++ | | ldh | NULL | +--------+-------------+
2、右外连接
右外连接又称为右连接,右连接是左连接的反向连接。使用right outer join关键字连接两个表,并使用on子句来设置连接。
--语法格式: select 字段名 from 表1 right out er join 表2 on子句; /* 与左连接相反,右连接以表2为基表,表1为参考表,查询时可以查询出表2中的所有记录行和表1中匹配连接条件的记录。如果表2的某行在表1中没有匹配行,那么在返回结果中,表1的字段值均为空值(NULL) */
案例:
在student123表和course表中查询所有学生姓名和相对应的课程名称,包括没有课程的学生
select student123.name,course.course_name from student123 right join course on student123.course_id=course.id;
+--------+-------------+ | name | course_name | +--------+-------------+ | Dany | Java | | Green | MySQL | | Henry | Java | | Jane | Python | | Jim | MySQL | | John | Go | | Lily | Go | | Susan | C++ | | Thomas | C++ | | Tom | C++ | | NULL | C | +--------+-------------+
四、分组查询
在MySQL中,group by关键字可以根据一个或多个字段对查询结果进行分组。
--语法格式: group by 字段名 --select后面有什么字段,这里的字段也必须是这些
案例:
根据student123表中的sex字段进行分组查询,统计每组人数
select sex,count(*) from student123 group by sex;
+-------+----------+ | sex | count(*) | +-------+----------+ | man | 6 | | woman | 5 | +-------+----------+
group by 与 group_concat()
group by关键字可以和group_concat()函数一起使用。group_concat()函数会把每个分组的字段值都显示出来。
select sex,group_concat(name) from student123 group by sex;
+-------+--------------------------------+ | sex | group_concat(name) | +-------+--------------------------------+ | man | Dany,Green,Jane,Lily,Susan,ldh | | woman | Henry,Jim,John,Thomas,Tom | +-------+--------------------------------+
在数据统计中,group by关键字经常和聚合函数一起使用
常见聚合函数
count() --用来统计记录的条数 sum() --用来计算字段值的总和 avg() --用来计算字段值的平均值 max() --用来查询字段的最大值 min() --用来查询字段的最小值
group by 与 with rollup
with rollup关键字用来在所有记录的最后加上一条记录,这条记录是上面所有记录的总和,即统计记录数量。
select sex,group_concat(name) from student123 group by sex with rollup;
+-------+----------------------------------------------------------+ | sex | group_concat(name) | +-------+----------------------------------------------------------+ | man | Dany,Green,Jane,Lily,Susan,ldh | | woman | Henry,Jim,John,Thomas,Tom | | NULL | Dany,Green,Jane,Lily,Susan,ldh,Henry,Jim,John,Thomas,Tom | +-------+----------------------------------------------------------+
五、子查询
子查询是MySQL中比较常用的查询方法,通过子查询可以实现多表查询。子查询指将一个查询语句嵌套在另一个查询语句中。子查询可以在select、update和delete语句中使用,而且可以进行多层嵌套。在实际开发中,子查询经常出现在where子句中。
--子查询在where子句中的语法格式 where 表达式 操作符 (子查询); --操作符可以是比较运算符和in、not in、exists、not exists等关键字 in --当表达式与子查询返回的结果集中的某个值相等时,返回true,否则返回false;若使用关键字not,则返回值正好相反 exists --用于判断子查询的结果集是否为空,若子查询的结果集不为空,返回true,否则返回fales;若使用关键字not,则返回值正好相反
案例:
使用子查询在student123表和course表中查询学习Java课程的学生姓名
select name from student123 where course_id=(select id from course where course_name='Java');
+-------+ | name | +-------+ | Dany | | Henry | +-------+
子查询的功能也可以通过表连接完成,但是子查询会使SQL语句更容易阅读和编写。 一般来说,表连接(内连接和外连接等)都可以用子查询替换,但反过来却不一定,有的子查询不能用表连接来替换。子查询比较灵活、方便、形式多样,适合作为查询的筛选条件,而表连接更适合与查看连接表的数据。