(二)SQL -- 查询

主要包含以下内容:

单表查询、子查询、多表查询(左连接右连接等)、合并查询

 

单表查询:

基础查询语句:

  select 列名

  from 表名

  where 条件     

  group by 列名

  order by 列名    

  having   //查询第二条件,常跟group by 配合使用

  limit 个数

where子句比较运算符:

  =     !=     <>    >     <      >=       <=  (不等于!=和<>均可)

  like   not like  

  is null   

  between...and...    

  in(值1,值2)      

通配符:

  • %     一个或多个字符  
  • _      单个字符

  如果需要查询包含%或_(即%和_不作为通配符),使用escape,例如:

  select * from tb1 where addr like '%/%g%' escape '/'  查找包含%g的(escape后的/也可以换成其他字符,但只能是单字符)

  select * from tb1 where addr like '%a%g%' escape 'a' (a后的%不作为通配符)

group by:

   按列不同值分组,常与avg、sum等聚合函数一起使用,(聚合函数和其他函数的根本区别就是他们一般作用于多条记录之上,只返回一个结果)

distinct:

  查询出所选列中,值不同的行

  select distinct 列1,列2 from 表名  //distinct对后面的列1,列2均有效

  select 列1,列2,列3 from 表名 group by 列1,列2,列3

  In most cases, a DISTINCT clause can be considered as a special case of GROUP BY. For example, the following two queries are equivalent: (distinct子句是group by的特例,以下两个语句等效)

  select distinct c1, c2, c3 from t1
  select c1, c2, c3 from t1 group by c1, c2, c3
having:
  第二查询条件,可以和sum,avg等函数一起使用,(对聚合函数计算后的结果进行筛选
  例如:

  select stu_name, sum(score) from tb1 group by stu_name having sum(score) > 60

  SELECT `name`, SUM(score) as gg from tb_1 group by name having gg > 200

where和having区别: 

  •   where无法跟合计函数一起使用,如:

        where sum(cnt) > 3   错误

        having sum(cnt) > 3  正确

  •   where作用于视图和表,having作用于组
  •   where在分组和聚集之前,选取输入行(它控制哪些行进入聚集运算);having在分组和聚集之后,选择分组的行
  •       where在查询结果返回之前起作用,having是对查询结果进行过滤
  •       where是对数据表中的字段进行判断,having是对查询结果中的字段进行判断
  •   having一般跟在group by之后,执行记录组选择的一部分来工作的,where则是执行所有数据来工作的

order by:

  对查询结果排序,默认升序。

  desc降序 (null值在最后)

  asc升序(null值在最前)

 limit:
  限定查询结果个数
  limit n; 取前n条数据
  limit n1, n2  // n1表示开始读取的第一条记录的编号(从0开始),n2表示要查询的记录个数
  例如:取查询结果的前10条记录
  limit 10;  
  limit 0,10;

 

子查询:

   一个查询结果可以作为另一个查询的条件 

  例1:查询book表中的记录,其中用户在user表中有登记的 select * from tb_books where user in (select user from tb_user)

  

  例2:有多个相同的最小值,要求查询出所有最小值的行   select * from tb1 where age in (select min(age) from tb1)

  

 

多表查询:

  多表查询有以下几种:

  • 内连接 inner join = join = from tb1, tb2  返回右表中和左表匹配的行(交集)
  • 左连接 left join = left outer join  返回左表所有的行,若右表没有匹配则补空行
  • 右连接 right join = right outer join  返回右表所有的行,若左表没有匹配则补空行
  • 全连接 full join = full outer join  返回所有行(笛卡尔积)

  注:

  1. 左连接的工作模式:从左表读出一条,选出所有与on匹配的右表记录(n条)进行连接,形成n条记录(包括重复的行)如果右表没有与on条件匹配的记录,那么连接的字段都是null然后继续下一条

  2. 内连接和多表条件查询等价(inner join和,(逗号)在语义上是等价的),以下两句等价;

  select 列名 from 表1 inner join 表2 on 条件

  select 列名 from 表1,表2 where 条件

  3. 当连接中on条件后为1=1,则为全连接。此时使用left join和right join效果相同,查询结果为左表中每一行和右表中每一行匹配,个数为左表的个数*右表的个数

  

  例如:两张原始表如下(人员表和订单表)

      

内连接

   列出所有人的订购(显示有订购的人和订购量)

select p.id_person, p.name, o.order_num
from tb_person p, tb_order o
where p.id_person = o.id_person  (多表查询)
select p.id_person, p.`name`, o.order_num from tb_person p inner join tb_order o on p.id_person = o.id_person  (内连接)

  

左连接

   列出所有的人,以及他们的订购(如果有订购的话)

select p.id_person, p.`name`, o.order_num from tb_person p left join tb_order o on p.id_person = o.id_person

  

右连接

   列出所有的订单,以及订购的人(如果有人订购的话)

select p.id_person, p.`name`, o.order_num from tb_person p right join tb_order o on p.id_person = o.id_person

  

全连接

   列出所有的人以及他们的订单,和所有的订单以及订购他们的人

  ps:Oracle支持full join,mysql不支持full join,但仍可以通过left join + union + right join来实现

select p.id_person, p.`name`, o.order_num from tb_person p left join tb_order o on p.id_person = o.id_person
union 
select p.id_person, p.`name`, o.order_num from tb_person p right join tb_order o on p.id_person = o.id_person

  

 

合并查询:

  合并两个或多个查询结果

  • union      会去重
  • union all 不去重,全部数据

  注:union内部的select语句必须拥有相同数量的列,且各列拥有相似的数据类型

 

 

 

 

 

 

 练习题1:

  以下两张表,tb_message文章表,tb_comment评论表。要求查找出所有文章的评论数,并按从大到小的顺序排序,若无评论,则为0

    

select a.id_message, a.title, count(b.id_comment) n from tb_message a left join tb_comment b on a.id_message = b.id_message 
group by a.id_message order by n desc

    

 练习题2:查询在左表,不在右表的记录 

   我们可以用右表没有on匹配则显示null的规律, 来找出所有在左表,不在右表的

select * from tb_message a left join tb_comment b on a.id_msg = b.id_msg where id_comment is null

        

 练习题3:查询左表中部分数据

查询左表或右表中的部分数据(带where子句),筛选条件放在where中,而不是on中

原始表如下:

  

1. 一般的左连接,查询出左表中的全部行,和右表中匹配的行,查询结果如下:

2. 只查询左表中部分数据,在右表中对应的行(有无用数据)

以下不报错,但左表中的全部行都在,存在很多不需要的数据行(因为不管on后的条件是否为真,都会返回左表中的全部行,而与on条件匹配的只有一行;左连接右连接同理)

以下语法错误,执行会报错:

3. 只查询左表中部分数据,在右表中对应的行(去除无用数据,方法1)(常用)

   (原理:先左连接查询,然后在查询的临时表中进行where筛选)

4. 只查询左表中部分数据,在右表中对应的行(去除无用数据,方法2)

   (原理:使用where,将左表当做子表,然后再使用左连接)

 

 

 

 

 

 

posted @ 2019-08-10 10:23  小虫虫大虫虫  阅读(355)  评论(0编辑  收藏  举报