多表查询和视图
多表查询
多表查询语法
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);
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`
视图
视图是从一个或者几个基本表或者视图中导出的虚拟表,是从现有基表中抽取若干子集组成用户的“专用表”,这种构造方式必须使用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.课程号;
更新视图
在SQL语句中,使用ALTER VIEW语句修改视图,其语法格式如下:
1 ALTER VIEW <视图名> [(字段名[,…])] 2 AS SELECT语句 3 [WITH CHECK OPTION];
例:修改上例中的视图v1。
1 alter view v1 2 as select 学号,姓名 from student;
删除视图
在SQL中,使用DROP VIEW语句删除视图,其语法格式如下:
1 DROP VIEW {视图名}[,…];
例:删除视图v1。
1 drop view v1;
-------------------