表与表之间的关系

11.1为什么要拆分表

拆分表的目的:

为了解决数据冗余问题,可以减少重复数据的存储,表的结构也更加清晰了

拆分之后:

在某些业务下,需要查询多个表,速度减低了

空间和时间

11.2表与表之间的关系

11.2.1 一对一

人与身份证的关系:

注意:

(1)一对一不存在数据冗余问题、可以不拆分表

(2)什么场景需要拆分?

用户信息+身份证+...-> 表中的字段太多了

11.2.2 一对多

最最常见的关系:

学生和成绩的关系:一个学生有多个成绩

部门和员工的关系:一个部门有多个员工

这种关系怎么去建立,怎么去表达

“多”的一方,存储“一”的主键id

在成绩表中存储用户的id

在员工表中存储部门的id

建表:使用主外键实现

11.2.3多对多

常见的案列:

老师与学生的关系:一个老师对应多位学生,一个学生对应多位老师

用户与商品的关系:

用户和权限的关系:

这种关系怎么去建立,怎么去表达:借助第三张表

用户和商品:订单(谁)(用户id)什么时候买了什么商品(商品id

订单Id

用户id

商品id

1001

1

6

1002

1

5

1003

3

6

 

 

用户和权限的关系:谁拥有什么权限

Id

用户id

权限id

1001

1

1001

1002

1

1003

1003

3

1001

 

11.3 多表查询

多表查询有如下几种:

(1)合并结果集:unionunion all

(2)连接查询(列的合并):

内连接:

外连接:

左外连接

右外连接

全连接

自然连接

(3)子查询

11.4合并结果集(行连接)

2个结果集(表)合并到一起

要求:2个结果集的列数(数据类型)应该要相同

11.4.1 union all(全部)

2个表的结果直接放在一起。不做任何的处理

Select * from t1

Union all

Select * from t2;

 

行增加了 列没有改变

11.4.2 union

2个表的结果直接放在一起。相同的数据只留下一个(去重)

Select * from t1

Union

Select * from t2;

 

11.5连接查询(列连接)

问题:学生表有十条数据,成绩表有十条数据

连接之后有多少条数据(笛卡尔积)10*10

连接查询会产生笛卡尔积;假设集合A={a,b},集合B={c,d}

2个集合的笛卡尔积{(a,c),(a,d),(b,c),(b,d)}

 

Select * from empdept

 

但是:

(1)从数据结果来讲,有很多无用的数据

(2)通过where条件过滤无用的数据:通过主外键来清楚无用数据

使用主外键清楚无用数据

Select * from emp,dept where emp.deptno=dept.deptno;

 

11.5.1 内连接 inner join

上面的写法其实就是内连接,但是不在SQL标准

标准写法:

select

*

 from

emp e

 inner join

 dept d

 On  

e.deptno=d.deptno;

 

(1)inner 可以省略

(2)内连接的特点:查询的条件必须满足条件,不满足条件的数据将会丢失

部门是40的数据就没有了,员工emp中没有40这个部门的人

 

11.5.2 外连接 outer join  outer可以省略)

左连接:

A left BA 左连接 B 表; A表示主表

B left AB 左连接 A表; B表示主表

右连接:

A right BA 右连接 B 表;B表示主表

B right AB 右连接 A 表;A表示主表

特点:主表的数据全部都在,

然后去匹配 非主表的 数据 ,匹配不上为null

员工表emp是主表,去匹配dept

   select

   *

 from

   emp e

 Left  join

   dept d

on  

   e.deptno=d.deptno;

 

部门表dept是主表,去匹配员工表 emp

select

 *

 from

   emp e

 Right  join

   dept d

 on  

   e.deptno=d.deptno;

面试题:左连接和右连接的区别

11.5.3自然连接  natural join

2张表中,有字段名字和数据类型一样 会自然作为连接的条件

Dept表中 emp都有deptno

   select

   *

   from

   emp e

 natural join

   dept d

  ;

 

 

11.6子查询

 

一个select查询中包含另外一个完整的select语句

子查询就是嵌套查询,一个select嵌套着一个或者多个select

11.6.1 子查询出现的位置

From后:作为一个表

Where:作为条件

In:在什么里面

Any:有一个

All:所有

##子查询

 

###1.查询工资 高于 JONES 的员工

1)先查JONES的工资。

select sal from emp where ename = 'JONES';

2)他的工资作为条件

select * from emp where sal > (第一步得到工资)

 

3)合并

select

*

from

emp

where

sal > (select sal from emp where ename = 'JONES');

 

##查询与SCOTT同一个部门的员工

 

select

*

from

emp

where

deptno = (select deptno from emp where ename = 'SCOTT');

 

##2.工资高于30号部门所有人的员工信息

##1)查询30部门的所有人的工资

select sal from emp where deptno = 30;

##2)查询高于30部门所有员工的信息

select

*

from

emp

where

sal > ALL (第一步所有的值)

##3)合并

select

*

from

emp

where

sal > ALL (select sal from emp where deptno = 30)

 

 

=============多行多列============

##查询 工作(job) 和 工资(sal) MARTIN 完全一样的员工信息

#(1)查看MARTIN的 工作和工资

select job,sal from emp where ename = "MARTIN";

+----------+---------+

| job      | sal     |

+----------+---------+

| SALESMAN | 1250.00 |

+----------+---------+

| SALESMAN | 150.00 |

+----------+---------+

 

#(2)根据员工信息

select

*

from

emp

where

(job,sal) in (第一步结果)

 

##3)合并之后

select

*

from

emp

where

(job,sal) in (select job,sal from emp where ename = "MARTIN") ;

 

 

==================多行单列--------

##找出有员工的部门信息

##1)找出所有 有员工的部门ID

select distinct deptno from emp;

+--------+

| deptno |

+--------+

|     30 |

|     20 |

|     10 |

+--------+

 

##2)找部门信息

select * from dept where deptno in (第一步的结果)

 

##3)合并

select * from dept where deptno in (select distinct deptno from emp);

 

 

 

##查询有2个以上直接下属的员工信息

##(1)找出各个领导的下属人数

 

select mgr, count(*) as cnt from  emp group by mgr ;

 

+------+-----+

| mgr  | cnt |

+------+-----+

| NULL |   1 |

| 7566 |   2 |

| 7698 |   5 |

| 7782 |   1 |

| 7788 |   1 |

| 7839 |   3 |

+------+-----+

 

select

t.mgr,t.cnt

from

(

select mgr, count(*) as cnt from  emp group by mgr

) t

where

   t.cnt > 2;

 

 +------+-----+

| mgr  | cnt |

+------+-----+

| 7698 |   5 |

| 7839 |   3 |

+------+-----+  

 

更简单方式:select mgr, count(*) as cnt from  emp group by mgr having   cnt > 2;

 

作业:

1.内存和硬盘的区别

2.IOE(马云,2016)、棱镜门事件

3.阿里云---王坚

4.Un

11.1为什么要拆分表

拆分表的目的:

为了解决数据冗余问题,可以减少重复数据的存储,表的结构也更加清晰了

拆分之后:

在某些业务下,需要查询多个表,速度减低了

空间和时间

11.2表与表之间的关系

11.2.1 一对一

人与身份证的关系:

注意:

(1)一对一不存在数据冗余问题、可以不拆分表

(2)什么场景需要拆分?

用户信息+身份证+...-> 表中的字段太多了

11.2.2 一对多

最最常见的关系:

学生和成绩的关系:一个学生有多个成绩

部门和员工的关系:一个部门有多个员工

这种关系怎么去建立,怎么去表达

“多”的一方,存储“一”的主键id

在成绩表中存储用户的id

在员工表中存储部门的id

建表:使用主外键实现

11.2.3多对多

常见的案列:

老师与学生的关系:一个老师对应多位学生,一个学生对应多位老师

用户与商品的关系:

用户和权限的关系:

这种关系怎么去建立,怎么去表达:借助第三张表

用户和商品:订单(谁)(用户id)什么时候买了什么商品(商品id

订单Id

用户id

商品id

1001

1

6

1002

1

5

1003

3

6

 

 

用户和权限的关系:谁拥有什么权限

Id

用户id

权限id

1001

1

1001

1002

1

1003

1003

3

1001

 

11.3 多表查询

多表查询有如下几种:

(1)合并结果集:unionunion all

(2)连接查询(列的合并):

内连接:

外连接:

左外连接

右外连接

全连接

自然连接

(3)子查询

11.4合并结果集(行连接)

2个结果集(表)合并到一起

要求:2个结果集的列数(数据类型)应该要相同

11.4.1 union all(全部)

2个表的结果直接放在一起。不做任何的处理

Select * from t1

Union all

Select * from t2;

 

行增加了 列没有改变

11.4.2 union

2个表的结果直接放在一起。相同的数据只留下一个(去重)

Select * from t1

Union

Select * from t2;

 

11.5连接查询(列连接)

问题:学生表有十条数据,成绩表有十条数据

连接之后有多少条数据(笛卡尔积)10*10

连接查询会产生笛卡尔积;假设集合A={a,b},集合B={c,d}

2个集合的笛卡尔积{(a,c),(a,d),(b,c),(b,d)}

 

Select * from empdept

 

但是:

(1)从数据结果来讲,有很多无用的数据

(2)通过where条件过滤无用的数据:通过主外键来清楚无用数据

使用主外键清楚无用数据

Select * from emp,dept where emp.deptno=dept.deptno;

 

11.5.1 内连接 inner join

上面的写法其实就是内连接,但是不在SQL标准

标准写法:

select

*

 from

emp e

 inner join

 dept d

 On  

e.deptno=d.deptno;

 

(1)inner 可以省略

(2)内连接的特点:查询的条件必须满足条件,不满足条件的数据将会丢失

部门是40的数据就没有了,员工emp中没有40这个部门的人

 

11.5.2 外连接 outer join  outer可以省略)

左连接:

A left BA 左连接 B 表; A表示主表

B left AB 左连接 A表; B表示主表

右连接:

A right BA 右连接 B 表;B表示主表

B right AB 右连接 A 表;A表示主表

特点:主表的数据全部都在,

然后去匹配 非主表的 数据 ,匹配不上为null

员工表emp是主表,去匹配dept

   select

   *

 from

   emp e

 Left  join

   dept d

on  

   e.deptno=d.deptno;

 

部门表dept是主表,去匹配员工表 emp

select

 *

 from

   emp e

 Right  join

   dept d

 on  

   e.deptno=d.deptno;

面试题:左连接和右连接的区别

11.5.3自然连接  natural join

2张表中,有字段名字和数据类型一样 会自然作为连接的条件

Dept表中 emp都有deptno

   select

   *

   from

   emp e

 natural join

   dept d

  ;

 

 

11.6子查询

 

一个select查询中包含另外一个完整的select语句

子查询就是嵌套查询,一个select嵌套着一个或者多个select

11.6.1 子查询出现的位置

From后:作为一个表

Where:作为条件

In:在什么里面

Any:有一个

All:所有

##子查询

 

###1.查询工资 高于 JONES 的员工

1)先查JONES的工资。

select sal from emp where ename = 'JONES';

2)他的工资作为条件

select * from emp where sal > (第一步得到工资)

 

3)合并

select

*

from

emp

where

sal > (select sal from emp where ename = 'JONES');

 

##查询与SCOTT同一个部门的员工

 

select

*

from

emp

where

deptno = (select deptno from emp where ename = 'SCOTT');

 

##2.工资高于30号部门所有人的员工信息

##1)查询30部门的所有人的工资

select sal from emp where deptno = 30;

##2)查询高于30部门所有员工的信息

select

*

from

emp

where

sal > ALL (第一步所有的值)

##3)合并

select

*

from

emp

where

sal > ALL (select sal from emp where deptno = 30)

 

 

=============多行多列============

##查询 工作(job) 和 工资(sal) MARTIN 完全一样的员工信息

#(1)查看MARTIN的 工作和工资

select job,sal from emp where ename = "MARTIN";

+----------+---------+

| job      | sal     |

+----------+---------+

| SALESMAN | 1250.00 |

+----------+---------+

| SALESMAN | 150.00 |

+----------+---------+

 

#(2)根据员工信息

select

*

from

emp

where

(job,sal) in (第一步结果)

 

##3)合并之后

select

*

from

emp

where

(job,sal) in (select job,sal from emp where ename = "MARTIN") ;

 

 

==================多行单列--------

##找出有员工的部门信息

##1)找出所有 有员工的部门ID

select distinct deptno from emp;

+--------+

| deptno |

+--------+

|     30 |

|     20 |

|     10 |

+--------+

 

##2)找部门信息

select * from dept where deptno in (第一步的结果)

 

##3)合并

select * from dept where deptno in (select distinct deptno from emp);

 

 

 

##查询有2个以上直接下属的员工信息

##(1)找出各个领导的下属人数

 

select mgr, count(*) as cnt from  emp group by mgr ;

 

+------+-----+

| mgr  | cnt |

+------+-----+

| NULL |   1 |

| 7566 |   2 |

| 7698 |   5 |

| 7782 |   1 |

| 7788 |   1 |

| 7839 |   3 |

+------+-----+

 

select

t.mgr,t.cnt

from

(

select mgr, count(*) as cnt from  emp group by mgr

) t

where

   t.cnt > 2;

 

 +------+-----+

| mgr  | cnt |

+------+-----+

| 7698 |   5 |

| 7839 |   3 |

+------+-----+  

 

更简单方式:select mgr, count(*) as cnt from  emp group by mgr having   cnt > 2;

 

作业:

1.内存和硬盘的区别

2.IOE(马云,2016)、棱镜门事件

3.阿里云---王坚

4.Unix  Linux

5.Svn  git

6.隐式转换 :就是不需要加强制转换, 系统会自动做这个操作

隐式转换有四种常见的使用场景:

将某一类型转换成预期类型

类型增强与扩展

模拟新的语法

类型类

 

7.Id号,不一定非得是数字

8.Sql的性能优化  (sql语句的优化背十个)

避免使用*,如果表中有100个字段 全部列出

模糊查询时候,避免使用通配符开头(避免全表扫描)

  1. 怎么获取中间的内容   

SUBSTRING_INDEX(SUBSTRING_INDEX(原字

ix  Linux

5.Svn  git

6.隐式转换 :就是不需要加强制转换, 系统会自动做这个操作

隐式转换有四种常见的使用场景:

将某一类型转换成预期类型

类型增强与扩展

模拟新的语法

类型类

 

7.Id号,不一定非得是数字

8.Sql的性能优化  (sql语句的优化背十个)

避免使用*,如果表中有100个字段 全部列出

模糊查询时候,避免使用通配符开头(避免全表扫描)

  1. 怎么获取中间的内容   

SUBSTRING_INDEX(SUBSTRING_INDEX(原字

posted @ 2021-04-28 09:22  四五  阅读(221)  评论(0)    收藏  举报