多表查询和视图

多表查询

多表查询语法

1 select
2     字段列表
3 from
4     表名列表
5 where
6     条件

使用多表查询出现的问题

 1 CREATE TABLE department(
 2     id INT PRIMARY KEY AUTO_INCREMENT,
 3     dep_name VARCHAR(5),
 4     dep_location VARCHAR(4)
 5 );
 6 
 7 CREATE TABLE employe(
 8     id INT PRIMARY KEY AUTO_INCREMENT,
 9     NAME VARCHAR(4),
10     age INT,
11     dep_id INT,# 外键列
12     
13     CONSTRAINT emp_dep_id FOREIGN KEY (dep_id) REFERENCES department(id)
14 
15 );
16 
17 
18 
19 INSERT INTO department (dep_name,dep_location)VALUES ('研发部','广州');
20 INSERT INTO department (dep_name,dep_location)VALUES ('销售部','深圳');
21 
22 
23 INSERT INTO employe (NAME,age,dep_id)VALUES ('张三',20,1);
24 INSERT INTO employe (NAME,age,dep_id)VALUES ('李四',20,1);
25 INSERT INTO employe (NAME,age,dep_id)VALUES ('王五',20,1);
26 INSERT INTO employe (NAME,age,dep_id)VALUES ('赵六',20,2);
27 INSERT INTO employe (NAME,age,dep_id)VALUES ('孙七',20,2);
28 INSERT INTO employe (NAME,age,dep_id)VALUES ('老八',20,2);
View Code

select * from 表名1,表名2;该语句的查询结果,有笛卡尔积(集合A,B,去两个表所有组合情况)表示:结果一共 X 行 (X=表1行数*表2行数)

那么就需要消除无用的数据

 解决方法:

  1,内连接查询

  2,外连接查询

  【交叉连接、自连接】

  3,子查询

  4,联合查询

内连接查询

隐式内连接

使用where条件来消除无用的数据

查询语句示例:

 1 # 查询所有字段
 2 SELECT * FROM employe,department WHERE employe.`dep_id` = department.`id`;
 3 
 4 # 查询部分字段
 5 SELECT 
 6     employe.`NAME`,employe.`id`,department.`dep_name`
 7 FROM
 8     employe,department
 9 WHERE
10     employe.`dep_id` = department.`id`;

显示内连接

select 字段列表 from 表名1 (inner) join 表名2 on 条件;

语法示例:

 1 # 查询全部字段
 2 SELECT * FROM employe JOIN department ON employe.`dep_id` = department.`id`;
 3 
 4 SELECT * FROM employe INNER JOIN department ON employe.`dep_id` = department.`id`;
 5 
 6 # 查询部分字段语法
 7 SELECT 
 8     employe.`NAME`,employe.`id`,department.`dep_name`
 9 FROM 
10     employe JOIN department 
11 ON 
12     employe.`dep_id` = department.`id`;

外连接查询

左外连接

语法

select 字段列表 from 表1 left (outer)join 表2 on 条件;查询的是左表(表1)所有获取左表所有记录,即使右表没有对应匹配的记录

左(外)连接,左表(a_table)的记录将会全部表示出来,而右表(b_table)只会显示符合搜索条件的记录。右表记录不足的地方均为NULL

交集指的是:符合条件的字段则就称为交集

1 SELECT * FROM employe LEFT JOIN department ON employe.`dep_id` = department.`id`;

右外连接

select 字段列表 from 表1 right【outer】 join 表2 on 条件;查询的是右表(表2)获取右表所有记录,即使左表没有对应匹配的记录

1 SELECT * FROM employe RIGHT JOIN department ON employe.`dep_id` = department.`id`;

子查询

查询中嵌套查询,称嵌套查询为子查询

1,子查询的结果是单行单列的:子查询可以作为条件,使用运算符去判断。运算符:>,>=,<,<=,=

        

2,子查询的结果是多行单列的:子查询可以作为条件,使用运算符IN来判断

3,子查询的结果是多行多列的:子查询可以作为一个虚拟表参与查询

4,any和all与比较运算符

4,Exists:判断返回的结果为T或者F

联合查询

 

多表查询大例子

  1 -- 部门表
  2 CREATE TABLE dept (
  3   id INT PRIMARY KEY PRIMARY KEY, -- 部门id
  4   dname VARCHAR(50), -- 部门名称
  5   loc VARCHAR(50) -- 部门所在地
  6 );
  7 
  8 -- 添加4个部门
  9 INSERT INTO dept(id,dname,loc) VALUES 
 10 (10,'教研部','北京'),
 11 (20,'学工部','上海'),
 12 (30,'销售部','广州'),
 13 (40,'财务部','深圳');
 14 
 15 
 16 
 17 -- 职务表,职务名称,职务描述
 18 CREATE TABLE job (
 19   id INT PRIMARY KEY,
 20   jname VARCHAR(20),
 21   description VARCHAR(50)
 22 );
 23 
 24 -- 添加4个职务
 25 INSERT INTO job (id, jname, description) VALUES
 26 (1, '董事长', '管理整个公司,接单'),
 27 (2, '经理', '管理部门员工'),
 28 (3, '销售员', '向客人推销产品'),
 29 (4, '文员', '使用办公软件');
 30 
 31 
 32 
 33 -- 员工表
 34 CREATE TABLE emp (
 35   id INT PRIMARY KEY, -- 员工id
 36   ename VARCHAR(50), -- 员工姓名
 37   job_id INT, -- 职务id
 38   mgr INT , -- 上级领导
 39   joindate DATE, -- 入职日期
 40   salary DECIMAL(7,2), -- 工资
 41   bonus DECIMAL(7,2), -- 奖金
 42   dept_id INT, -- 所在部门编号
 43   CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
 44   CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
 45 );
 46 
 47 -- 添加员工
 48 INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES 
 49 (1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
 50 (1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
 51 (1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
 52 (1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
 53 (1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
 54 (1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
 55 (1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
 56 (1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
 57 (1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
 58 (1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
 59 (1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
 60 (1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
 61 (1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
 62 (1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);
 63 
 64 
 65 
 66 -- 工资等级表
 67 CREATE TABLE salarygrade (
 68   grade INT PRIMARY KEY,   -- 级别
 69   losalary INT,  -- 最低工资
 70   hisalary INT -- 最高工资
 71 );
 72 
 73 -- 添加5个工资等级
 74 INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
 75 (1,7000,12000),
 76 (2,12010,14000),
 77 (3,14010,20000),
 78 (4,20010,30000),
 79 (5,30010,99990);
 80 
 81 -- 需求:
 82 
 83 -- 1.查询所有员工信息。查询员工编号,员工姓名,工资,职务名称,职务描述
 84 SELECT 
 85     t1.`id`,
 86     t1.`ename`,
 87     t1.`salary`,
 88     t2.`jname`,
 89     t2.`description`
 90 FROM
 91     emp t1,job t2
 92 WHERE
 93     t1.`job_id`=t2.`id`;
 94 
 95 
 96 -- 2.查询员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
 97 SELECT 
 98     t1.`id`,
 99     t1.`ename`,
100     t1.`salary`,
101     t2.`jname`,
102     t2.`description`,
103     t3.`dname`,
104     t3.`loc`
105 FROM
106     emp t1,job t2,dept t3
107 WHERE
108     t1.`job_id`=t2.`id` AND t1.`dept_id` = t3.`id`;
109 
110    
111    
112 -- 3.查询员工姓名,工资,工资等级
113 SELECT 
114     t1.ename,
115     t1.`salary`,
116     t2.`grade`
117 FROM 
118     emp t1,salarygrade t2
119 WHERE
120     -- t1.`salary`=<t2.`hisalary` and t1.`salary`>=t2.`losalary`
121     t1.`salary` BETWEEN t2.`losalary` AND t2.`hisalary`;
122 
123 
124  
125 -- 4.查询员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
126 SELECT 
127     t1.`ename`,
128     t1.`salary`,
129     t2.`jname`,
130     t2.`description`,
131     t3.`dname`,
132     t3.`loc`,
133     t4.`grade`
134 FROM 
135     emp t1,job t2,dept t3,salarygrade t4
136 WHERE
137     t1.`job_id` = t2.`id` AND
138     t1.`dept_id` = t3.`id` AND
139     t1.`salary` BETWEEN t4.`losalary` AND t4.`hisalary`;
140 
141 
142 
143 -- 5.查询出部门编号、部门名称、部门位置、部门人数    
144 SELECT 
145     t1.`id`,
146     t1.`dname`,
147     t1.`loc`,
148     t2.t3
149 FROM 
150     dept t1,( SELECT dept_id,COUNT(id) t3 FROM emp GROUP BY dept_id) t2
151     
152 WHERE 
153     t1.`id`=t2.dept_id;
154 
155  
156  
157 -- 6.查询所有员工的姓名及其直接上级的姓名,没有领导的员工也需要查询
158 SELECT
159     t2.`ename`,
160     t2.`mgr`,
161     t1.`ename`,
162     t1.id
163 FROM 
164     emp t1,emp t2
165 WHERE
166     t1.`id`=t2.`mgr`;
167 
168 
169 -- 自关联映射 起别名    
170 SELECT
171     t1.`ename`,
172     t2.`ename`
173 
174 FROM 
175     emp t1
176     LEFT JOIN emp t2
177     ON t1.`mgr`=t2.`id`
View Code

视图

视图是从一个或者几个基本表或者视图中导出的虚拟表,是从现有基表中抽取若干子集组成用户的“专用表”,这种构造方式必须使用SQL中的SELECT语句来实现。

使用视图具有如下优点。

(1)简化对数据的操作。

(2)自定义数据。

(3)数据集中显示。

(4)导入和导出数据。

(5)合并分割数据。

(6)安全机制。

创建视图

在SQL中,使用CREATE VIEW语句创建视图,其语法格式如下:

1 CREATE [OR REPLACE] VIEW <视图名> [(字段名[,…])]
2 AS SELECT语句
3 [WITH CHECK OPTION];

 

例:在数据库D_sample中定义视图查询学生的姓名、课程名称和成绩

1 use D_sample;
2 
3 create view v1
4 as
5 select 姓名,课程名称,成绩
6 from student a,course b,sc c
7 where a.学号=c.学号 and b.课程号=c.课程号;
View Code

 

更新视图

在SQL语句中,使用ALTER VIEW语句修改视图,其语法格式如下:

1 ALTER VIEW <视图名> [(字段名[,…])]
2 AS SELECT语句
3 [WITH CHECK OPTION];

 

例:修改上例中的视图v1。

1 alter view v1
2 as      select 学号,姓名 from student;
View Code

删除视图

在SQL中,使用DROP VIEW语句删除视图,其语法格式如下:

1 DROP VIEW {视图名}[,…];

 

例:删除视图v1。

1 drop view v1;
View Code

 

 

 

 

 

 

 

 

 

 

 

-------------------

posted @ 2020-03-19 19:01  YKKY  阅读(1239)  评论(0编辑  收藏  举报