MySQL-复杂查询及条件-起别名-多表查询-04

目录

  • 基本查询语句及方法
  • 测试数据创建
    • 创建数据库与表
    • 插入表记录数据
  • 数据展示
    • 常见结果排版
    • 另一种结果排版 \G
  • 简单查询语句的书写与执行顺序
    • 查询语句书写
    • 执行顺序
    • 科普-- 起别名
      • 写法
    • 可以对字段做四则运算(加减乘数)
    • concat 格式化拼接字段
    • concat_ws 用指定字符拼接字段
  • 定制化查询结果
    • 常见的数据定制化关键字(非多表查询)
    • where 结合过滤条件过滤结果
      • > < = != <= >= <> 比较运算符
      • and or not 与或非连接多个条件
      • is
      • 范围
      • exists 是否存在
      • like 模糊匹配
      • regexp 正则
    • group by 分组
      • 应用场景
      • 分组严格模式(推荐开启)
    • having 分组条件
      • 分组结合聚合函数
    • distinct 去重
    • order by 排序
    • limit 限制展示数据的条数
      • 练习
      • 应用场景
  • 究极版执行顺序书写顺序
    • 书写顺序(除了 select ... from ... 其他是可选的)
    • 执行顺序
  • 多表查询
    • 前言
    • 测试数据创建
      • 创建数据库与表
      • 插入表记录数据
    • 笛卡尔集/积 -- 科普
    • 联表查询
      • 内连接 inner join ... on
      • 左连接 left join ... on
      • 右连接 right join ... on
      • 全连接 union ... on
    • 子查询
    • 练习小案例

基本查询语句及方法

测试数据创建

如果在windows系统中,插入中文字符,select的结果为空白,可以将所有字符编码统一设置成gbk(或者参照我安装配置MySQL的博客,将所有字符编码设置为 utf8)

创建数据库与表

create database db1;
use db1;

create table emp(
  id int not null unique auto_increment,
  # 表内没有字段是primary key,innodb的机制,一个表没有primaryk key时会自动将 not null + unique的键自动升级为 primary key 主键
  name varchar(20) not null,
  sex enum('male','female') not null default 'male',  # 大部分是男的
  age int(3) unsigned not null default 28,  # 这个3 只限制了显示宽度,并不影响存储
  hire_date date not null,
  post varchar(50),
  post_comment varchar(100),
  salary double(15,2),
  office int,  # 一个部门一间办公室,一个门牌号
  depart_id int  # 暂不建立外键关系
);

插入表记录数据

# 三个部门:教学,销售,运营
# 以下是教学部
insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
('jason','male',18,'20170301','张江第一帅形象代言',7300.33,401,1),
('egon','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tank','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jerry','female',18,'20110211','teacher',9000,401,1),
('nick','male',18,'19000301','teacher',30000,401,1),
('sean','male',48,'20101111','teacher',10000,401,1),

# 以下是销售部门
('歪歪','female',48,'20150311','sale',3000.13,402,2),
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

# 以下是运营部门
('张野','male',28,'20160311','operation',10000.13,403,3),
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3);

数据展示

常见结果排版

select * from emp;

另一种结果排版 \G

当表字段特别多的时候,结果的排版可能会出现混乱的现象,你可以在语句最后加 \G 来改变排版,方便查看

比较差的展示结果,这种情况就非常适合用 \G 来看数据

简单查询语句的书写与执行顺序

查询语句书写

查询出 emp 表中id 在 3~6 的员工详细信息

思路:从emp 表中,查 id 大于3 且 小于 6 的数据

语句

select * from emp where id > 3 and id < 6;

这里仅为了演示书写顺序,不考虑其他写法

执行顺序

最先执行的是 from,来确定到底是哪张表

然后执行 where,根据条件筛选数据

最后执行 select,来拿筛选出来的数据中的(某些,select 后面跟的字段名)字段

科普-- 起别名

关键字 as

  • 可以给表起别名
  • 可以给查询出来的虚拟表(查询结果)起别名
  • 可以给字段起别名
  • 可以给函数的结果取别名(max、min 等)

写法

要起别名的对象 as 别名 或者 直接 要起别名的对象 别名

不过尽量还是用as ,不用as 可能语义不明确

给函数结果起别名

... max(hire_date) as max_date ...

给表起别名

select ... from emp as t1 ....

给查询出来的虚拟表取别名

... (select * from emp) as t2 ...

给字段起别名

select name as ‘姓名‘, post ‘部门‘ from emp;

可以对字段做四则运算(加减乘数)

查一下 jason 的年薪

select name as ‘姓名‘, salary * 12 as ‘年薪‘ from emp where name = ‘jason‘;

concat 格式化拼接字段

可以按指定格式拼接字段

select concat('oldboy_', name, '_', id), sex, post, salary from emp;

concat_ws 用指定字符拼接字段

select concat_ws(‘:‘, name, sex, age) from emp;

定制化查询结果

复杂查询实现小窍门:

写sql语句的时候,千万不要急着一口气写完(切忌心浮气躁)

前期按照歩鄹一步步写将前一步操作产生的结果当成是一张新的表,然后基于该表再进行其他操作,写一步查询看一下结果然后基于当前结果再往后写

我们查询数据一般都需要做一些过滤,单纯靠 select * from 表名; 就无法达到要求,此时我们可以通过

常见的数据定制化关键字(非多表查询)

  • where 条件过滤数据

    一般配合一堆聚合函数使用

  • group by 对数据进行分组

    • having 对分组的结果再进行条件过滤(必须跟在 group by 语句后面)

  • distinct 对查询结果去重

  • order by 对查询结果排序

  • limit 限制显示数据条数

where 结合过滤条件过滤结果

> < = != <= >= <> 比较运算符

# 查询出 emp 表中, id 大于3 的员工信息
select * from emp where id > 3;

and or not 与或非连接多个条件

一般用来连接多个条件

and 并且

or 或

not 非

is

针对 null 判断的时候只能用 is 不能用 =

案例

# and
# 1.查询id大于等于3小于等于6的数据
select id,name from emp where id >= 3 and id <= 6;

# or
# 2.查询薪资是20000或者18000或者17000的数据
select * from emp where salary = 20000 or salary = 18000 or salary = 17000;

# not
# 5.查询id小于3或者大于6的数据
select *  from emp where id not between 3 and 6;

# is
# 7.查询岗位描述为空的员工名与岗位名  针对null不能用等号,只能用is
select name,post from emp where post_comment = NULL;  # 查询为空,不能用 = 判断空!
select name,post from emp where post_comment is NULL;
select name,post from emp where post_comment is not NULL;

范围

between ... and ... 表示范围(整型字段可用)

in

and or not 结果其他关键字组合

案例

# between ... and ...
# 1.查询id大于等于3小于等于6的数据
select *  from emp where id between 3 and 6;

# in
# 2.查询薪资是20000或者18000或者17000的数据
select * from emp where salary in (20000,18000,17000);

# and or not
# 在上一模块中有案例

exists 是否存在

# EXISTS 关键字表示存在
# 返回值是 True 或者 False
select * from emp where exists (select id from dep where id > 203);  # 用到了下面的子查询(知识点)

like 模糊匹配

一般包含有 ... 之类的查询都会用 like 关键字,模糊匹配

小技巧

是否含有用 % 包围起来

固定长度用 来占位,一个 _ 表示一个字符

案例

# 3.查询员工姓名中包含o字母的员工姓名和薪资
select name,salary from emp where name like '%o%';

# 4.查询员工姓名是由四个字符组成的员工姓名与其薪资
# 方案一:用四个 _ 代替四个字符
select name,salary from emp where name like '____';
# 方案二:利用 char_length(字段名) 来获取字段长度
select name,salary from emp where char_length(name) = 4;  # 注意 sql_mode 里 PAD_CHAR_TO_FULL_LENGTH 这么个约束,否则 char类型定长可能会受影响

regexp 正则

可用正则规则匹配字符串作为查询条件

select * from emp where name regexp ‘^j.*(n|y)$‘;

group by 分组

分组之后应该做到最小单位是组,而不应该再展示组内的单个信息

MySQL 中分组之后,只能拿到分组的字段信息无法直接获取其他字段信息

但是你可以通过其他方法(如:聚合函数)间接地获取

分组相当于打包,聚合函数可以对包里每一个元素进行处理,最终拿出想要的

刚开始查询表,一定要按照最基本的步骤,先确定是哪张表,再确定查这张表也没有限制条件,再确定是否需要分类,最后再确定需要什么字段对应的信息

应用场景

每个部门的平均薪资,男女比例等

分组严格模式(推荐开启)

select * from emp group by post; 如果你的MySQL不报错,说明分组的严格模式没有设置

--> only_full_group_by 限制分组

非分组严格模式下

设置分组严格模式(其他的严格模式别忘写了)

set global sql_mode=‘strict_trans_tables,pad_char_to_full_length,only_full_group_by‘;

pad_char_to_full_length 验证 char varchar占用空间用,会影响 char_length() 获取的长度

strict_trans_tables 限制 sql 不能不合规则的直接报错

分组严格模式下执行,直接报错(day37.emp.id --> 数据库day37.表emp.字段id),字段不在分组里

having 分组条件

havingwhere 是一模一样的,也是用来筛选数据的,但是 having 必须在 group by 后面使用

where是对整体数据做一个初步的筛选,而having是对分组之后的数据再进行一次针对性的筛选

select post, avg(salary) from emp where age > 30 group by post having avg(salary) > 10000;

统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门

分组结合聚合函数

只能在分组之后使用(如果没有写group by ,默认所有数据就是一组

也可以说是 where 不能用聚合函数(执行顺序过了 where之后就可也以算分组之后了--> 执行顺序)

max min avg sum count

能够获取到分组之后除了分组依据以外的字段,将该字段作为函数的条件

# 强调:只要分组了,就不能够再“直接”查找到单个数据信息了,只能获取到组名
# 2.获取每个部门的最高工资
# 以组为单位统计组内数据>>>聚合查询(聚集到一起合成为一个结果)
# 每个部门的最高工资
select post,max(salary) from emp group by post;
# 每个部门的最低工资
select post,min(salary) from emp group by post;
# 每个部门的平均工资
select post,avg(salary) from emp group by post;
# 每个部门的工资总和
select post,sum(salary) from emp group by post;

# 每个部门的人数
# 在统计分组内个数的时候,填写任意非空字段都可以完成计数(推荐使用能够标识数据的字段,比如id字段)
select post,count(id) from emp group by post;

group_concat 分组拼接记录字段

能够获取到分组之后除了分组依据以外的字段,还能做拼接操作

# 3.查询分组之后的部门名称和每个部门下所有的学生姓名
# group_concat(分组之后用)不仅可以用来显示除分组外字段还有拼接字符串的作用
select post,group_concat(name) from emp group by post;

select post,group_concat(name,"_SB") from emp group by post;

select post,group_concat(name,": ",salary) from emp group by post;

select post,group_concat(salary) from emp group by post;

# 4.补充concat(不分组时用)拼接字符串达到更好的显示效果 as语法使用(前面有讲到)
select name as 姓名,salary as 薪资 from emp;
select concat("NAME: ",name) as 姓名,concat("SAL: ",salary) as 薪资 from emp;

/*
concat  在不分组情况下使用
group_concat  用在分组之后
*/

distinct 去重

对整个查询(查询出的虚拟表)结果中重复的数据去重,重复必须数据是一模一样的才能去重,只要有一个(字段)不一样都不能算是重复的数据

如果你查询出来的数据中包含主键(非空且唯一),那么不可能去重成功

个人推荐理解成作用于上一步查询结果的(不要以为像order by一样修饰某个字段)

select distinct age, id from emp;

查询结果有重复的情况下,会自动去除重复

select distinct sex, age, id from emp order by sex, age asc;

记录没有重复,distinct 无效

order by 排序

order by 有升序(ASC)、降序(DESC)两种排序规则,默认升序

多个排序字段时,放前面的作为优先排序条件,相同再按照后面的字段排序

select post, avg(salary) from emp where age>10 group by post having avg(salary) > 1000 order by avg(salary);

单个字段排序

select * from emp order by sex, age asc;

多字段排序

limit 限制展示数据的条数

select * from emp limit 3;

当limit 只有一个参数的时候,表示的是从第一条开始只展示几条

select * from emp limit 5,5;

当limit 有两个参数的时候,第一个参数表的起始位置,第二个参数表示从起始位置开始往后展示的条数

练习

查询工资最高的人的详细信息

select * from emp order by salary desc limit 1;

应用场景

分页数据展示,每页只展示多少条,每页展示的内容,是第几条到第几条

究极版执行顺序书写顺序

书写顺序(除了 select ... from ... 其他是可选的)

select distinct 字段1,字段2(有分组时只能写分组字段或聚合函数) from 表名
where 条件(不能用聚合函数)
group by (单个)字段
having 条件
order by 字段1,字段2 排序规则
limit 起始位置,条数;

执行顺序

from
where
group by
    having  # 必须跟在 group by 后面
# 后4个顺序不太重要,也不一定对
order by
limit
distinct
select

多表查询

前言

在昨天的知识点中,员工信息全存为一张表不太合理,我们选择了拆表,分析了表关系,最终拆分成了员工表与部门表两张表,表示拆分好了,但怎么去查询数据呢?

实现多表查询,有下面两种方式

  • 联表查询
  • 子查询

每一次的查询结果都是一张虚拟表,我们可以用 as 关键字给虚拟表取别名,然后将其当做普通表作为查询条件使用

测试数据创建

创建数据库与表

create database db2;
use db2;

create table dep(
id int,
name varchar(20)
);

create table emp(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

插入表记录数据

insert into dep values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营');

insert into emp(name,sex,age,dep_id) values
('jason','male',18,200),
('egon','female',48,201),
('kevin','male',38,201),
('nick','female',28,202),
('owen','male',18,200),
('jerry','female',18,204);

# 当初为什么我们要分表,就是为了方便管理,在硬盘上确实是多张表,但是到了内存中我们应该把他们再拼成一张表进行查询才合理

笛卡尔集/积 -- 科普

笛卡尔集的列数为每个表的列数之和,笛卡尔集的行数为每个表的行数相乘

我们经常做的多表查询就是在笛卡尔集中通过筛选条件得出的数据,所以笛卡尔集是多表查询的基础

select * from emp, dep; 结果是一个笛卡尔集/积

select * from emp;

select * from dep;

后面跟条件也可以达到多表查询

select * from emp, dep where emp.dep_id = dep.id

联表查询

通过下面四种连接语句来实现多表查询

inner/left/right join ...左右是表 on ... 后面可以跟条件

内连接 inner join ... on

仅保留两张表有对应关系的记录

select * from emp inner join dep on emp.dep_id=dep.id;

左连接 left join ... on

在内连接的基础上保留左表没有对应关系的记录

select * from emp left join dep on emp.dep_id = dep.id;

右连接 right join ... on

在内连接的基础上保留右表没有对应关系的记录

select * from emp right join dep on emp.dep_id = dep.id;

全连接 union ... on

不常用

在内连接的基础上保留左、右面表没有对应关系的的记录

写法:只需要在左连接和右连接的sql 语句中间加个union就变成了全连接

select * from emp left join dep on emp.dep_id = dep.id  # 左连接 sql,后面不要加分号
union
select * from emp right join dep on emp.dep_id = dep.id;  # 右连接 sql

子查询

将一个查询语句用括号括起来,将查询结果(虚拟表)作为另外一个 sql 语句的查询条件

ps:表的查询结果可以作为其他表的查询条件,也可以通过起别名的方式把它作为一张虚拟表跟其他表做关联查询

# 1.查询部门是技术或者人力资源的员工信息

# 思路
# 先获取技术部和人力资源部的id号,再去员工表里面根据前面的id筛选出符合要求的员工信息
select * from emp where dep_id in (select id from dep where name = "技术" or name = "人力资源");

select * from emp;

select id from dep where name = "技术" or name = "人力资源";

# 2.每个部门最新入职的员工

# 思路
# 先查每个部门最新入职的员工,再按部门对应上联表查询

select t1.id, t1.name, t1.hire_date, t1.post from emp as t1
inner join
# 根据分组求出最新入职员工
(select post,max(hire_date) as max_date from emp group by post) as t2
on t1.post = t2.post
where t1.hire_date = t2.max_date;

完整表信息

练习小案例

# 平均年龄在25岁以上的部门名

# 联表
select dep.name from dep inner join emp on emp.dep_id = dep.id group by dep.name having avg(age) > 25;

# 子查询
select name from dep where dep.id in (select dep_id from emp group by dep_id having avg(age) > 25);

联表查询思路

1.先把两张表连起来,把结果查出来看看,再接着往下写

select * from dep inner join emp on emp.dep_id = dep.id;

2.再根据部门分组,筛选出平均年龄大于25的部门名

group by dep.name having avg(age) > 25

合并上一步的语句(* --> dep.name)

select dep.name from dep inner join emp on emp.dep_id = dep.id group by dep.name having avg(age) > 25;

子查询思路

1.先根据 部门id 分组,查出平均年龄大于 25多的部门id

select dep_id from emp group by dep_id having avg(age) > 25;

2.将上一步的 部门id 作为筛选条件 联合上部门表查出来

select name from dep where dep.id in (select dep_id from emp group by dep_id having avg(age) > 25);

原文地址:https://www.cnblogs.com/suwanbin/p/11396463.html

时间: 2024-10-13 13:57:29

MySQL-复杂查询及条件-起别名-多表查询-04的相关文章

Django Mysql数据库-基于双下划线的跨表查询

一.基于双下划线的跨表查询 Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系.要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止.(相当于用sql语句用join连接的方式,可以在settings里面设置,可查看sql语句) 数据库模型: class Book(models.Model): nid = models.AutoField(primary_key=Tru

MySQL存储引擎 SQL数据导入/导出 操作表记录 查询及匹配条件

MySQL存储引擎的配置 SQL数据导入/导出 操作表记录 查询及匹配条件 1 MySQL存储引擎的配置1.1 问题 本案例要求MySQL数据存储引擎的使用,完成以下任务操作: 可用的存储引擎类型 查看默认存储类型 更改表的存储引擎 1.2 步骤 实现此案例需要按照如下步骤进行. 步骤一:查看存储引擎信息 登入MySQL服务器,查看当前支持哪些存储引擎. 使用mysql命令连接,以root用户登入: [[email protected] ~]# mysql -u root –p Enter pa

MySQL查询数据表中数据记录(包括多表查询)

MySQL查询数据表中数据记录(包括多表查询) MySQL查询数据表中数据记录(包括多表查询) 转自:http://www.baike369.com/content/?id=5355 在MySQL中创建数据库的目的是为了使用其中的数据. 使用select查询语句可以从数据库中把数据查询出来. select语句的语法格式如下: select selection_list // 要查询的内容,选择哪些列 from table_list // 从什么表中查询,从何处选择行 where primary_

mysql 增删改查,表查询(重点)

十一.数据的增删改: 本节重点: 插入数据 INSERT 更新数据 UPDATE 删除数据 DELETE 再来回顾一下之前我们练过的一些操作,相信大家都对插入数据.更新数据.删除数据有了全面的认识.那么在mysql中其实最重要的不是这三大操作,而是查数据最重要,下节课知晓 一. 在MySQL管理软件中,可以通过SQL语句中的DML语言来实现数据的操作,包括 1.使用INSERT实现数据的插入 2.UPDATE实现数据的更新 3.使用DELETE实现数据的删除 4.使用SELECT查询数据以及.

mysql如何查询多样同样的表/sql分表查询、java项目日志表分表的开发思路/按月分表

之前开发的一个监控系统,数据库的日志表是单表,虽然现在数据还不大并且做了查询sql优化,不过以后数据库的日志表数据肯定会越来越庞大,将会导致查询缓慢,所以把日志表改成分表,日志表可以按时间做水平分表,我是按月分的,每个月一张表,这时候的问题是 数据库有多张同样的分表如何根据条件查询? 在进行分页的时候如何计算总记录数?如何查询出所有分表? 每个月的新表是如何创建?系统如何自动创建? 不确定哪个分表的情况如何查询某一条详细记录? 分表查询分表查询可以用union或者union all进行查询uni

Mysql 查询命令--单表查询

基本查询语句 SELECT语句是最常用的查询语句,它的使用方式有些复杂,但功能是相当强大的.SELECT语句的基本语法如下: select selection_list //要查询的内容,选择哪些列 from 数据表名 //指定数据表 where primary_constraint //查询时需要满足的条件,行必须满足的条件 group by grouping_columns //如何对结果进行分组 order by sorting_cloumns //如何对结果进行排序 having sec

Oracle基础(五):多表查询

一.多表查询 (一)简单多表查询 1.多表查询的机制 1)SQL: SELECT * FROM emp; --14条记录 SELECT * FROM dept;--4条记录 SELECT * FROM emp,dept;--显示56条数据??为什么 2)分析: 先从 dept 选择一条记录(deptno=10).分别于 emp中的14条记录分别匹配.显示14条记录. 再从 dept 选择一条记录(deptno=20),分别于 emp中的14条记录分别匹配.显示14条记录. 依次类推. water

Oracle 多表查询(2)

四.统计函数及分组查询 1.统计函数 在之前学习过一个COUNT()函数,此函数的功能可以统计出表中的数据量,实际上这个就是一个统计函数,而常用的统计函数有如下几个: COUNT():查询表中的数据记录: AVG():求出平均值: SUM():求和: MAX():求出最大值: MIN():求出最小值: 范例:测试COUNT().AVG().SUM() 统计出公司的所有雇员,每个月支付的平均工资及总工资. SELECT MAX(sal),MIN(sal) FROM emp; 注意点:关于COUNT

SQL Fundamentals || 多表查询(内连接,外连接(LEFT|RIGHT|FULL OUTER JOIN),自身关联,ON,USING,集合运算UNION)

一.多表查询基本语法 在进行多表连接查询的时候,由于数据库内部的处理机制,会产生一些“无用”的数据,而这些数据就称为笛卡尔积. 多表查询时可以利用等值关联字段消除笛卡尔积 多表查询之中,每当增加一个关联表都需要设置消除笛卡尔积的条件 分析过程很重要: 确定所需要的数据表 确定已知的关联字段: 按照SQL语句的执行步骤编写:FROM,WHERE,SELECT,ORDER BY (由于SELECT是在WHERE子句之后执行,所以SELECT子句所定义的别名WHERE不可以直接使用) (由于SELEC