#数据库--第2章 数据库查询


  这一章节将会介绍所有的数据库查询方法,使用的数据是 上一章 介绍和导入的数据。

一、基础查询


  1、投影操作

  1.1 选取属性列

-- 查询 orders 表中所有 O_CLERK 字段的值
select O_CLERK from orders;

    关键字 distinct 表示取消重复行

select distinct O_CLERK from orders;

    给 O_CLERK 起别名为 clerk

select distinct O_CLERK clerk from orders;

  1.2 算数表达式

select distinct O_TOTALPRICE, O_TOTALPRICE / 100 new_O_TOTALPRICE from orders;

  1.3 函数

select distinct O_TOTALPRICE, round(O_TOTALPRICE) round_O_TOTALPRICE from orders;

  1.4 常量
  注意:常量既可以是字符常量,也可以是数值常量

select 'used', O_TOTALPRICE, 'dollar', 1 from orders;

  2、条件查询

  2.1 比较大小
  注意:不等于有两种表示方法: !=、<>

select O_TOTALPRICE from orders where O_TOTALPRICE > 300000;

  2.2 范围查询
  关键字为:[not] between…and…

select O_TOTALPRICE from orders where O_TOTALPRICE between 200000 and 300000;
select O_TOTALPRICE from orders where O_TOTALPRICE not between 200000 and 300000;

  2.3 确定集合
  关键字为:[not] in (…)
  注意:一个查询结果表可以视为一个集合

select distinct O_ORDERDATE, O_ORDERSTATUS from orders where O_ORDERSTATUS in ('O', 'F');
select distinct O_ORDERDATE, O_ORDERSTATUS from orders where O_ORDERSTATUS not in ('O', 'F');

  2.4 字符匹配
  关键字为:[not] like
  % 表示任意长度的任意字符

select distinct O_CLERK from orders where O_CLERK like '%1';

  _ 表示长度为 1 的任意字符

select distinct O_CLERK from orders where O_CLERK like 'Clerk#00000095_';

  若想要查询的字符串含有 %、 _ ,可以使用转义字符 \

select distinct O_COMMENT from orders where O_COMMENT like '\%1';

  也可以用 escape 指定转义字符

select distinct O_COMMENT from orders where O_COMMENT like '*%1' escape '*';

  2.5 涉及空值 NULL 的查询
  关键字:is [not] null

select distinct O_CLERK from orders where O_COMMENT is null;
select distinct O_CLERK from orders where O_COMMENT is not null;

  2.6 多重条件查询
  关键字:and、or

select distinct * from orders where O_TOTALPRICE between 299900 and 300000 and O_ORDERSTATUS in ('O');
select distinct * from orders where O_TOTALPRICE between 299900 and 300000 or O_ORDERSTATUS in ('O');

  3、排序

  关键字 order by … [asc|desc]
  asc 即 ascend 升序

select distinct O_ORDERDATE, O_TOTALPRICE from orders order by O_ORDERDATE asc;

  desc 即 descend 降序

select distinct O_ORDERDATE, O_TOTALPRICE from orders order by O_ORDERDATE desc;

  4、函数

  SQL 函数分为两大类:1、聚集函数(Aggregate Function) 2、标量函数(Scalar Function)
  聚集函数:多个输入,一个输出
  常用的有:
    SUM() - 返回总和
    AVG() - 返回平均值
    COUNT() - 返回行数
    MAX() - 返回最大值
    MIN() - 返回最小值
    FIRST() - 返回第一个记录的值
    LAST() - 返回最后一个记录的值
  
  标量函数:多个输入,多个输出,例如:
  常用的有:
    UCASE() - 将某个字段转换为大写
    LCASE() - 将某个字段转换为小写
    MID() - 从某个文本字段提取字符,MySql 中使用
    SubString(字段,1,end) - 从某个文本字段提取字符
    LEN() - 返回某个文本字段的长度
    ROUND() - 对某个数值字段进行指定小数位数的四舍五入
    NOW() - 返回当前的系统日期和时间
    FORMAT() - 格式化某个字段的显示方式


  5、分组

  关键字:group by … [having aggregate_function()]
  group by 的执行过程为:
    1、从 from 指定的表中执行 where 得到结果
    2、之后再用 group by 指定的字段进行分组
    3、对于每一组,再执行 having 语句,得到筛选后的分组
    4、对于每一组,再执行 select 语句,若存在多个值,则只返回第一个值
  注意:如果有某一组有多个值,则只给出第一个值

select O_TOTALPRICE, O_ORDERSTATUS from orders group by O_ORDERSTATUS;

  注意:进行分组后 select 语句里的函数将会分别作用于每一组

select count(O_TOTALPRICE), O_ORDERSTATUS from orders group by O_ORDERSTATUS;

  having 关键字也是进行条件筛选
  SQL 中增加 having 子句原因是,where 关键字无法与聚合函数一起使用
  如果有 group by 子句,那么 having 将会作用于每个组,否则作用和 where 一样

select count(O_TOTALPRICE), O_ORDERSTATUS from orders group by O_ORDERSTATUS having count(O_ORDERSTATUS) > 5000;
select O_TOTALPRICE, O_ORDERSTATUS from orders having O_ORDERSTATUS in ('O', 'F');

  6、总结

  1、select 可以接 字段名、函数、算术表达式、常量。
  2、查询条件可以是:逻辑运算、范围比较、集合判断、字符匹配(注意特殊字符:%、_、\)及其所有逻辑组合
  3、可以用 distinct 来去除重复行,用 order by … [asc|desc] 来对结果进行排序,用 group by [having] 对结果进行分组处理(若某组结果有多个值,select 后只返回第一个值)
  4、函数分为聚集函数(Aggregate Function) 和标量函数(Scalar Function),并记住常用函数。
  5、查询条件关键字有 having 和 where,having 在 group by 之后执行,可以搭配聚合函数使用,where 在 group by 之前执行,只能搭配标量函数使用


二、连接查询

注意:无论是普通连接还是外连接,若一个表的一个元组与另一个表的多个元组满足连接条件,则会将这个表的此元组会重复地与另一个表的元组进行连接。


  1、普通连接

  普通连接又称为内连接,即通过 where 条件将多个表进行连接,表既可以是不同的表,也可以是同一张表

select * from nation, region where nation.N_REGIONKEY = region.R_REGIONKEY;

  若字段名称可区分,前面的表名可省略

select * from nation, region where N_REGIONKEY = R_REGIONKEY;

  若为同一个表进行连接,则应给表起别名加以区分

select distinct A.L_ORDERKEY from lineitem A, lineitem B where A.L_COMMITDATE = B.L_SHIPDATE;

  2、外连接

  外连接包括左外连接、右外连接、全外连接
  2.1 左外连接
  关键字为:… left [outer] join … on …
  左外连接即,对于左表的每一个元组在右表寻找所有满足连接条件的元组,进行连接。若没有满足条件的,则右表置为 NULL 进行连接

select * from nation left outer join region on N_REGIONKEY = R_REGIONKEY;

  2.2 右外连接
  关键字为 … right [outer] join … on …
  右外连接即,对于右表的每一个元组在左表寻找所有满足连接条件的元组,进行连接。若没有满足条件的,则左表置为 NULL 进行连接

select * from nation right outer join region on N_REGIONKEY = R_REGIONKEY;

  2.3 全外连接
  关键字为:… full join … on …
  全外连接即左外连接和右外连接的综合

select * from nation full join region on N_REGIONKEY = R_REGIONKEY;

三、嵌套查询

  嵌套查询即,将一个完整的查询语句作为另一个查询语句的 where 或 having 子句
  注意:嵌套的子句不能使用 order by
  
  3.1-3.3 都属于不相关子查询,即查询子句和外层查询语句无关联
  不相关子查询执行过程为:由里及外,逐层查询
  3.4 属于相关子查询,即查询子句依赖于外层查询语句
  相关子查询的执行过程为:依次选取外层查询的每一行记录,放入子查询里进行查询


  1、带 in 谓词的嵌套查询

  注意:如果子句结果不唯一只能用 in ,若结果唯一则 = 、in 都可以

-- 查询在 orders 里订单状态为 O、F 的顾客出现次数大于二十的姓名和地址
select C_NAME, C_ADDRESS from customer where C_CUSTKEY in 
(select O_CUSTKEY from orders where O_ORDERSTATUS in ('O', 'F') group by O_CUSTKEY having count(O_CUSTKEY) > 20);

  2、带比较运算符的嵌套查询

  注意:只有当子句结果唯一是才能用才能用比较运算符

-- 查询账户金额小于订单号为 279812 的订单金额的客户
select * from customer where C_ACCTBAL < (select O_TOTALPRICE from orders where O_ORDERKEY = 279812);

  3、带 any、all 谓词的子查询

  注意:需要搭配使用比较运算符
   >any: 大于子查询结果中的某个值
   >all:  大于子查询结果中的所有值
   <any: 小于子查询结果中的某个值
   <all:  小于子查询结果中的所有值
   >=any: 大于等于子查询结果中的某个值
   >=all:  大于等于子查询结果中的所有值
   <=any: 小于等于子查询结果中的某个值
   <=all:  小于等于子查询结果中的所有值
   = any:  等于子查询结果中的某个值
   =all:   等于子查询结果中的所有值(通常没有实际意义)
   !=(或<>)any: 不等于子查询结果中的某个值
   !=(或<>)all:  不等于子查询结果中的任何一个值

-- 查询账户金额小于 9116 号顾客下的订单的金额的账户
select * from customer where C_ACCTBAL <all (select O_TOTALPRICE from orders where O_CUSTKEY = 9116);

  4、带 [not] exists 谓词的子查询

  注意:[not] exists 只是用来判断子查询是否为空,exists 若子查询结果为空返回 true,否则返回 false,not exists 相反。

-- 查询所有订单日期为 1996-01-02 的客户姓名
select C_NAME from customer where exists (select * from orders where O_CUSTKEY=C_CUSTKEY and O_ORDERDATE='1996-01-02');

  5、总结

  1、所有带 in、any、all、比较运算符的子查询都能用 exists 等价替换,反之则不一定
  2、从执行过程不难看出,相关子查询速度会比不相关子查询要慢,所以写嵌套查询的时候应尽量避免相关子查询语句


四、集合查询

  一次查询结果可以视为一个集合,自然就会有集合操作:交、并、差
  要求进行集合操作的两个表的列数一样且每列的数据类型对应相同


  1、并

  关键字:union [all]
  注意:union 会自动去掉重复行, union all 则保留重复行

-- 查询订单金额大于 500000 或者 订单日期在 1993-1-1 之前的订单
select * from orders where O_TOTALPRICE > 500000 union select * from orders where O_ORDERDATE < '1993-1-1';

  2、交

  关键字:intersect
  注意:mysql 不支持集合交操作

-- 查询订单金额大于 500000 且 订单日期在 1993-1-1 之前的订单
select * from orders where O_TOTALPRICE > 500000 intersect select * from orders where O_ORDERDATE < '1993-1-1';

  3、差

  关键字:except
  注意:mysql 不支持集合差操作

-- 查询订单金额大于 500000 且 订单日期不在 1993-1-1 之前的订单
select * from orders where O_TOTALPRICE > 500000 except select * from orders where O_ORDERDATE < '1993-1-1';

五、最后总结

  sql 语句的执行顺序为:from -> join -> on -> where -> group by -> function -> having -> select -> distinct -> order by


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值