MySQL多表查询和函数使用及其例题

多表查询

笛卡尔乘积现象

  • 表查询中的笛卡尔乘积现象:多行表在查询时,如果定义了无效连接或者漏写了连接条件,就会产生笛卡尔乘积现象,所谓的笛卡尔乘积即是每个表的每一行都和其他表的每一行组合。

###

SELECT * FROM DEPT,EMP;

image-20230728120605500

等值连接查询

  • 常是在存在主键外键关联关系的表之间的连接进行,使用"="连接相关的表

  • 注:n个表进行等值连接查询,最少需要n-1个等值条件来约束

查询每个部门的所有员工
select d.dname,e.ename from emp e ,dept d where d.deptno = e.deptno;

自连接查询

  • 表表查询不仅可以在多个表之间进行查询,也可以在一个表之中进行多表查询

查询当前公司员工和所属上级员工的信息
 select e1.empno as 员工编号,e1.ename as 员工姓名,e2.empno as 领导编号,e2.ename as 领导姓名 from emp as e1,emp as e2 where e1.mgr = e2.empNo;

内连接查询

  • 内连接查询使用inner join关键字实现,inner可以省略。内连接查询时,条件用 on连接,多个条件使用()将其括起来.

查询每个部门的所有员工
select dept.name,emp.name from emp inner join dept on emp.deptno = dept.deptno;

外连接

  • 外连接分为左外连接(left outer join) 和右外连接(right outer join)其值outer可以省略。外连接查询时,条件用 on连接,多个条件使用()将其括起来.

  • 左外连接表示以左表为主表,右外连接表示以右表为主表。查询时将主表信息在从表中进行匹配

查询每个员工所属的部门
select dept.name,emp.name from emp right join dept on emp.deptno = dept.deptno;
查询每个部门的所有员工
select dept.name,emp.name from emp left join dept on emp.deptno = dept.deptno;

子查询

单行子查询

 查询软件部门下的所有员工
 select * from emp e where e.deptno = (select d.deptno from dept d where d.dname = '软件部门';

单行多列

查询公司中和员工相同薪水和奖金的员工
​
select * from emp e1 where (e1.sal,e1.comm) = (select e2.sal,e2.comm from emp e2 
where e2.ename = 'scott');
​

多行子查询

  • 如果子查询返回了多行记录,则称这样的嵌套查询为多行子查询,多行子查询就需要用到多行记录的操作符

    如: in , all , any(some) in 子查询中所有的记录

    any 表示大于子查询中的任意一个值,即大于最小值

    all 表示大于子查询中的所有值,即大于最大的值

问题

  • 在使用了 GROUP BY 的 SQL 中, ORDER BY 可以使用 聚合函数 吗? 可以使用未在 GROU P BY 中出现的列吗?

    order by 可以使用聚合函数,不可以使用未在group by 中出现的列
    SELECT deptno, COUNT(*) FROM emp GROUP BY deptno ORDER BY count(*) DESC, empno 
    
    ASC; -- 可以执行吗?
    答:不可以执行
可以使用子查询,有限制,mysql的功能问题
mysql不支持对同一个表查询后做修改(update、delete)操作 

DELETE FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'SCOTT'); 
是否可以
答:不可以,同表查询应该设置别名

子查询[应用]

  • 单列子查询

    查看 emp 表中与 SMITH 岗位相同的员工信息
     select  * from emp e where job=(select job from emp e1 where ename='smith');
    
  • 单行子查询

  • 多行子查询

    查询 与 SMITH 在同一个部门且岗位相同的员工的信息
     select * from emp e where (e.deptno,e.job)=(select e1.deptno,e1.job from emp e1 where ename='smith');
    查询emp表中与20部门员工岗位相同的员工信息

单行函数

image-20230728172019185

注:这里的字符串是从1开始的(不是0)

练习

  • 将 emp 表中雇员姓名首字母大写其余字母小写. 如 SCOTT => Scott

  • select concat( upper(substr(ename,1,1)), lower(substr(ename,2))) from emp;
  • 给每个雇员的 JOB 前加上 KFM- 前缀

     select concat('kfm-',job) from emp;
  • 给每个雇员的 JOB 后加上部门名称

     select concat('job-',d.dname) from emp e join dept d on d.deptno=e.deptno ;

数学函数

image-20230728173825754

日期函数

image-20230728173955728

image-20230728174027366

image-20230728174048171

image-20230728174101471

--type值可以是:
MICROSECOND 微秒
SECOND 秒
MINUTE 分钟
HOUR 小时
DAY 天
WEEK 周
MONTH 月
QUARTER 季度
YEAR 年
MINUTE_SECOND 分钟:秒
HOUR_SECOND 小时:分钟 : 秒
HOUR_MINUTE 小时:分钟
DAY_SECOND 天 小时:分钟:秒
DAY_MINUTE 天 小时:分钟
DAY_HOUR 天 小时
YEAR_MONTH 年-月
--可以被用在format字符串:
%M 月名字(January……December)
%W 星期名字(Sunday……Saturday)
%D 有英语前缀的月份的日期(1st, 2nd, 3rd, 等等。)
%Y 年, 数字, 4 位
%y 年, 数字, 2 位
%a 缩写的星期名字(Sun……Sat)
%d 月份中的天数, 数字(00……31)
%e 月份中的天数, 数字(0……31)
%m 月, 数字(01……12)
%c 月, 数字(1……12)
%b 缩写的月份名字(Jan……Dec)
%j 一年中的天数(001……366)
%H 小时(00……23)
%k 小时(0……23)
%h 小时(01……12)
%I 小时(01……12)
%l 小时(1……12)
%i 分钟, 数字(00……59)
%r 时间,12 小时(hh:mm:ss [AP]M)
%T 时间,24 小时(hh:mm:ss)
%S 秒(00……59)
%s 秒(00……59)
%p AM或PM
%w 一个星期中的天数(0=Sunday ……6=Saturday )
%U 星期(0……52), 这里星期天是星期的第一天
%u 星期(0……52), 这里星期一是星期的第一天

练习

  • 计算公司员工入职的天数

    select ename, concat((datediff(now(),hiredate)),'天') as 入职天数 from emp;
  • 计算公司员工入职的月数

     select ename, concat((TIMESTAMPDIFF(month,hiredate,now())),'月') as 入职月份 from emp;
  • 计算公司员工入职的年份

     select ename, concat((TIMESTAMPDIFF(year,hiredate,now())),'年') as 入职月份 from emp;
  • 入职41年以上的员工 工资涨 2000

     update emp set salary=salary+2000 where TIMESTAMPDIFF(year,hiredate,now()) > 41;
  • 显示在 2 月份入职的员工信息

     select * from emp where month(hiredate)= 2;
  • 显示在星期三入职的员工信息

    select * from emp where weekday(hiredate)= 3;
  • 假设 SCOTT 入职时 24 岁,现在多大了?

     select ename,(TIMESTAMPDIFF(year,hiredate,now())+24) as 年龄 from emp where ename='scott';
  • 员工试用期为 3 个月,显示他们转正日期

     select emp.*, date_add(hiredate,interval 3 month) as 转正日期 from emp;
  • 所用到日期函数

    data_add('日期',interval 日期类型) 、 timestampdiff(返回的日期类型,'日期','日期')、month('日期')、weekday('日期')

设计数据库步骤

软件开发的步骤大致上可以分为: 需求分析,概要设计,详细设计,代码编写,运行测试,部署发行 数据库是在代码编写前完成的 数据库设计可分为这几个过程 需求分析,概念模型,逻辑模型,物理模型,运行验证

创建概念模型

P74~p84

数据库设计范式

  • 数据库的设计有五大设计范式。常用的有三大设计范式,称之为第一范式( 1NF ),第二范 式( 2NF ),第三范式( 3NF ),他们是逐步为严格的,满足第二范式,就必须满足先满足第 一范式。满足第三范式时就必须首先满足第二范式

  • 第一范式(1NF)

  • 第二范式(2NF)

  • 第三范式(3NF)

  • 巴斯-科德范式(BCNF)

  • 第四范式(4NF)

数据库范式

第一范式

第一范式要求单个表中每个列必须是原子列(即每一个列都是不可再分的最小数据单 元),列不存在重复属性,每个实体的属性也不存在多个数据项。

1.原子列

2.不出现重复属性

3.不允许出现多个数据项

第二范式

第二范式是在满足第一范式的基础之上,要求数据表里的所有数据都要和该数据表的主键 有完全依赖关系。

第三范式

第三范式是在满足第二范式的基础之上,每一个非主键列都直接依赖主键列,不依赖其他 非主键列,即数据库中不能存在传递函数的依赖关系。

范式的优缺点

优点:

\1. 范式化的数据库更新起来更加的快;

\2. 范式化之后只有很少的重复数据,只需要修改更少的数据;

\3. 范式化的表更小,可以在内存中直接执行;

\4. 很少的冗余数据,在查询时候需要更少的distinct后者group by语句。 缺点:

\1. 范式化的设计会产生更多的表;

\2. 在查询的时候经常需要很多的表连接查询,到值查询性能降低;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值