多表查询与子查询

问题的引出:

多表查询与子查询_第1张图片

这里有一个留言板,其中一条评论包含了商品名称good(商品表),留言content(留言表)。 那么请问如将这个评论从数据库查询出来?这就涉及到了多表查询

多表查询是指基于两个和两个以上的表查询.在实际应用中,查询单个表可能不能满足你的需求。

笛卡尔集

首先新建三张表并插入测试数据

#新建一张部门表
create table dept (
				deptno MEDIUMINT  UNSIGNED  NOT NULL DEFAULT 0,
				dname varchar(20) not null default '',
				loc varchar(13) not null default '');
INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK'),(20,'RESEARCH','DALLAS'),(30,'SALES','CHICAGO'),(40,'OPERATIONS','BOSTON');
#新建一张员工表
create table emp (
				empno MEDIUMINT unsigned not null default 0,
				ename varchar(20) not null default '',  /* 名字*/
				job varchar(9) not null default '',
				mgr mediumint unsigned , /* 上级编号*/
				hiredate date not null, /* 入职时间*/
				sal  decimal (7,2) not null , /* 薪水*/
				comn decimal(7,2), /* 红利*/
				deptno MEDIUMINT unsigned not null default 0);  /* 部门编号*/
				
INSERT INTO emp VALUES (7369,'SMITH','CLERK', 7902, '1990-12-17', 800.00, NULL , 20);
INSERT INTO emp VALUES ( 7499,'ALLEN' , 'SALESMAN', 7698, '1991-2-20', 1600.00, 300.00, 30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN', 7698,'1991-2-22', 1250.00, 500.00, 30);
INSERT INTO emp VALUES (7566,'JONES','MANAGER', 7839,'1991-4-2', 2975.00, NULL, 20);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,'1991-9-28',1250.00,1400.00,30);
INSERT INTO emp VALUES (7698, 'BLAKE', 'MANAGER', 7839,'1991-5-1', 2850.00, NULL, 30);
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,'1991-6-9',2450.00,NULL,10);
INSERT INTO emp VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1997-4-19', 3000.00, NULL, 20);
INSERT INTO emp VALUES (7839, 'KING', 'PRESIDENT' , NULL, '1991-11-17' , 5000.00, NULL,10);
INSERT INTO emp VALUES (7844,'TURNER', 'SALESMAN', 7698, '1991-9-8', 1500.00, NULL, 30);
INSERT INTO emp VALUES (7900, 'JAMES', 'CLERK' , 7698, '1991-12-3', 950.00, NULL, 30);
INSERT INTO emp VALUES (7902,'FORD', 'ANALYST', 7566, '1991-12-3', 3000.00, NULL, 20);
INSERT INTO emp VALUES (7934,'MILLER' , 'CLERK', 7782,'1992-1-23', 1300.00,NULL, 10) ;
SELECT * from emp;

#工资级别表
CREATE TABLE salgrade 
(
 grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, -- 级别
losal DECIMAL(17,2) NOT NULL, -- 该级别最低工资
hisal DECIMAL(17,2) NOT NULL); -- 该级别最高工资

RENAME TABLE salgradegrade TO salgrade;

INSERT INTO salgrade VALUES(2, 1201, 1400);
INSERT INTO salgrade VALUES(3,1401, 2000);
INSERT INTO salgrade VALUES(4, 2001, 3000);
INSERT INTO salgrade VALUES(5,3001,9999);
INSERT INTO salgrade VALUES(1,700,1200);

 ?显示部门、工资、及所在部门的名称

分析:显示部门编号、工资 需要 查询emp表

          显示部门名称需要查询 dept 表

          在不加where子句的情况下, 先来看 select * from emp,dept (查询两张表用逗号隔开) 返回的结果。总共52条记录。

多表查询与子查询_第2张图片

        那么这52条记录是如何查出来的呢? 从结果来看,每一个员工都对应了所有部门。

多表查询与子查询_第3张图片

 ?显示部门、工资、及所在部门的名称

在笛卡尔积当中,一个员工对应了4个部门,我们只需要部门编号deptno相等的那个部门,所以加上where子句进行过滤。

SELECT emp.deptno,sal,dept.dname from dept,emp where emp.deptno = dept.deptno

多表查询 

多表查询SQL书写思路 :  首先要对表结构高度熟悉。  先用?代替select的具体colunm,  然后考虑需要查询的表是哪几张(from),再考虑筛选条件(where)

-- 显示各个员工的姓名,工资,及其工资的级别
SELECT ename,sal,salgrade.grade 
             from emp,salgrade 
			 where sal BETWEEN salgrade.losal AND salgrade.hisal
-- 如何显示部门号为10的部门名、员工名和工资
SELECT dept.dname,ename,sal ,emp.deptno from dept,emp 
			 where emp.deptno = dept.deptno AND emp.deptno=10;
															
-- 显示雇员名,雇员工资及所在部门的名字,并按部门排序[降序排].
SELECT ename,sal,dept.dname 
             from emp, dept 
			 where emp.deptno = dept.deptno 
			 ORDER BY emp.deptno desc;

自连接

自表连接是指在同一张表上的连接查询。

? 显示公司员工和他的上级的名字 

 -- 显示公司员工和他的上级的名字
 SELECT temp.ename , emp.ename as boss 
                      from emp ,emp as temp  
					  where emp.empno = temp.mgr

子查询

概念 :      子查询是指嵌入在其它sql语句中的select语句,也叫嵌套查询

单行子查询

    单行子查询是指只返回一行数据的子查询语句。

-- 如何显示与smith在同一个部门的员工
SELECT * from emp where deptno = (
				SELECT deptno FROM emp
				where ename = 'SMITH');
																

多行子查询

    多行子查询指返回多行数据的子查询, 使用关键字in

-- 如何查询和部门10的工作相同的雇员的名字、岗位、工资、部门号,但是不含10号部门自己的雇员
-- 分析 首先查10 部门的job
SELECT job from emp where deptno = '10';	
--然后使用子查询
SELECT ename,job,sal,deptno from emp where job in (
				SELECT job from emp
				where deptno = '10'
				)
				and deptno != 10;

子查询临时表

先创建一张商品表并插入测试数据

CREATE TABLE goods_l (
						goods_id INT,
						cat_id INT,
						goods_name VARCHAR(32),
						shop_price DOUBLE );
insert into goods_l VALUES 
				(1,2,'奥利奥',15.00),
				(2,2,'好丽友',20.00),
				(3,3,'卫龙',2.00),
				(4,3,'巧乐兹',5.00),
				(5,4,'可爱多',5.00),
				(6,4,'东方树叶',5.00);
	

-- 查询ecshop中各个类别中,价格最高的商品

	-- 查询ecshop中各个类别中,价格最高的商品.
	-- 分析先查询出 各个类别中的 价格最高
	SELECT cat_id ,MAX(shop_price) from goods_l GROUP BY cat_id;
	-- 再使用临时表
	SELECT goods_l.* from goods_l,( 
							SELECT cat_id ,MAX(shop_price) as max_good 
							from goods_l
							GROUP BY cat_id
					      ) goods 
					 where goods_l.cat_id= goods.cat_id and shop_price = max_good;

查询结果

多表查询与子查询_第4张图片

关键字 ALL 与 ANY

-- 请思考:如何显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

-- 请思考:如何显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
SELECT ename,sal,deptno from emp where sal >ALL(
																																		 
     SELECT sal from emp where deptno = '30');
SELECT ename,sal,deptno from emp where sal >(
																																		 
  SELECT MAX(sal) from emp where deptno = '30');

 -- 请思考:如何显示工资比部门30的其中一个员工的工资高的员工的姓名、工资和部门号

-- 请思考:如何显示工资比部门30的其中一个员工的工资高的员工的姓名、工资和部门号
SELECT ename,sal,deptno from emp where sal >ANY(
																																		 
 SELECT sal from emp where deptno = '30');

多列子查询

多列子查序则是指查询返回多个列数据的子查询语句

(字段1,字段2...)=(select 字段1,字段2 from。。。。)

-- 请思考如何查询与smith的部门和岗位完全相同的所有雇员(并且不含smith本人)

#请思考如何查询与smith的部门和岗位完全相同的所有雇员(并且不含smith本人)																											
-- 先分析 查询smith的部门与岗位
SELECT deptno,job FROM emp WHERE ename = 'SMITH';	
SELECT * from emp WHERE (deptno,job) = (
                                SELECT deptno,job FROM emp  
								WHERE ename = 'SMITH'
				  ) AND ename != 'SMITH';				

子查询练习

# 请思考:如何显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
SELECT ename,sal,deptno from emp where sal >ALL(
																																		SELECT sal from emp where deptno = '30');
# 请思考:如何显示工资比部门30的其中一个员工的工资高的员工的姓名、工资和部门号
SELECT ename,sal,deptno from emp where sal >ANY(
																																		SELECT sal from emp where deptno = '30');
--
#请思考如何查询与smith的部门和岗位完全相同的所有雇员(并且不含smith本人)																											
# 先分析 查询smith的部门与岗位
SELECT deptno,job FROM emp WHERE ename = 'SMITH';	
SELECT * from emp WHERE (deptno,job) = (
                                      SELECT deptno,job FROM emp  
																																			 
                                      WHERE ename = 'SMITH'
				 ) AND ename != 'SMITH';																																				

你可能感兴趣的:(mysql学习,数据库)