SQL基础二

前期准备:

--部门表
dept部门表(deptno部门编号/dname部门名称/loc地点)
create table dept (
    deptno numeric(2),
    dname varchar(14),
    loc varchar(13)
);

insert into dept values (10, 'ACCOUNTING', 'NEW YORK');
insert into dept values (20, 'RESEARCH', 'DALLAS');
insert into dept values (30, 'SALES', 'CHICAGO');
insert into dept values (40, 'OPERATIONS', 'BOSTON');

--工资等级表
salgrade工资等级表(grade 等级/losal此等级的最低/hisal此等级的最高)
create table salgrade (
    grade numeric,
    losal numeric,
    hisal numeric
);

insert into salgrade values (1, 700, 1200);
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);


--员工表
emp员工表(empno员工号/ename员工姓名/job工作/mgr上级编号/hiredate受雇日期/sal薪金/comm佣金/deptno部门编号)
工资 = 薪金 + 佣金

1.表自己跟自己连接

create table emp (
    empno numeric(4) not null,
    ename varchar(10),
    job varchar(9),
    mgr numeric(4),
    hiredate datetime,
    sal numeric(7, 2),
    comm numeric(7, 2),
    deptno numeric(2)
);



insert into emp values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);
insert into emp values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);
insert into emp values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);
insert into emp values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);
insert into emp values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);
insert into emp values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);
insert into emp values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);
insert into emp values (7788, 'SCOTT', 'ANALYST', 7566, '1982-12-09', 3000, null, 20);
insert into emp values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);
insert into emp values (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500, 0, 30);
insert into emp values (7876, 'ADAMS', 'CLERK', 7788, '1983-01-12', 1100, null, 20);
insert into emp values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);
insert into emp values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);
insert into emp values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);

1.求员工表所有人的薪水和

select 
sum(sal) as "total salary"
from emp;

total salary|
------------|
    29025.00|

2.求员工表的各个部门的薪水和

select 
deptno,
sum(sal) as salary
from emp 
group by deptno;

deptno|salary  |
------|--------|
    10| 8750.00|
    20|10875.00|
    30| 9400.00|

3.求员工表的各个部门的薪水和、员工数、平均薪资

select 
deptno,
sum(sal) as "salary summary",
count(ename) as "people count",
sum(sal)/count(ename) as "mean salary",
avg(sal) as "avg salary"
from emp 
group by deptno;

deptno|salary summary|people count|mean salary|avg salary |
------|--------------|------------|-----------|-----------|
    10|       8750.00|           3|2916.666667|2916.666667|
    20|      10875.00|           5|2175.000000|2175.000000|
    30|       9400.00|           6|1566.666667|1566.666667|

4.找薪水和大于9000的是哪个部门

方法一、用having过滤
select 
deptno,
sum(sal) as "salary summary"
from emp
group by deptno
having sum(sal)>9000;

deptno|salary summary|
------|--------------|
    20|      10875.00|
    30|       9400.00|

方法二、 用子查询
select *
from
(select 
deptno,
sum(sal) as ssal
from emp
group by deptno) as t where t.ssal>9000;

deptno|ssal    |
------|--------|
    20|10875.00|
    30| 9400.00|

5.排序order by

Select * from salgrade order by hisal;
默认顺序是从小到大(asc),后面加上desc就是从大到小排序。
grade|losal|hisal|
-----|-----|-----|
    1|  700| 1200|
    2| 1201| 1400|
    3| 1401| 2000|
    4| 2001| 3000|
    5| 3001| 9999|


Select * from salgrade order by hisal, losal desc;
多个条件排序,用逗号分隔
grade|losal|hisal|
-----|-----|-----|
    1|  700| 1200|
    2| 1201| 1400|
    3| 1401| 2000|
    4| 2001| 3000|
    5| 3001| 9999|

6.聚合group by

聚合函数sum求合,count求数量,avg求平均,max求最大值,min求最小值
Select deptno, sum(sal) from emp group by deptno;
deptno|sum(sal)|
------|--------|
    10| 8750.00|
    20|10875.00|
    30| 9400.00|

聚合语法,一般group by和聚合函数正常来说是放在一起使用
Group by 字段必须出现select 字段,select后面的字段一定要和同句语句中group by后面的字段对等,如select 后面是部门,group by 后面也要是部门。处理聚合函数的字段,如sum(sal)这个求工资和的字段无需和group by后面对等。
As 别名,相当于重新对字段命名
过滤having,相当于where条件,只是在这里用having,having一定是跟在group by 后面。

数量,最大值等比较特殊,后面不需要用group by
如:select count(*) from emp;
Select max(sal) from emp;

7.综合运用

select 
deptno,
job,
sum(sal) as ssum,
count(sal) as pcount
from emp 
where deptno !=10                 
group by deptno,job               
order by deptno,ssum desc         
limit 2;           

deptno|job    |ssum   |pcount|
------|-------|-------|------|
    20|ANALYST|6000.00|     2|
    20|MANAGER|2975.00|     1|                

8.连接:JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接。

数据准备
create table testa(aid int,aname varchar(100),address varchar(100));
create table testb(bid int,bname varchar(100),age int);
create table testc(cid int,sal int);
insert into testa values(1,'x1','sh');
insert into testa values(2,'x2','hz');
insert into testa values(3,'x3',null);
insert into testa values(4,'x4','bj');
insert into testa values(5,'x5','gz');

select * from testb
insert into testb values(1,'x1',10);
insert into testb values(2,'x2',11);
insert into testb values(3,'x3',12);
insert into testb values(4,'x4',16);

insert into testb values(7,'x7',19);
insert into testb values(8,'x8',22);
insert into testb values(9,'x9',24);
insert into testb values(10,'x10',44);

内连接:INNER JOIN
内连接INNER JOIN是最常用的连接操作。从数学的角度讲就是求两个表的交集,从笛卡尔积的角度讲就是从笛卡尔积中挑出ON子句条件成立的记录。有INNER JOIN,WHERE(等值连接),STRAIGHT_JOIN,JOIN(省略INNER)四种写法。

select 
a.*,
b.*
from testa as a 
inner join testb as b  on a.aid=b.bid;
aid|aname|address|bid|bname|age|
---|-----|-------|---|-----|---|
  1|x1   |sh     |  1|x1   | 10|
  2|x2   |hz     |  2|x2   | 11|
  3|x3   |       |  3|x3   | 12|
  4|x4   |bj     |  4|x4   | 16|

左连接:LEFT JOIN
左连接LEFT JOIN的含义就是求两个表的交集外加左表剩下的数据。依旧从笛卡尔积的角度讲,就是先从笛卡尔积中挑出ON子句条件成立的记录,然后加上左表中剩余的记录

select 
a.*,
b.*
from testa as a 
left join testb as b  on a.aid=b.bid;

aid|aname|address|bid|bname|age|
---|-----|-------|---|-----|---|
  1|x1   |sh     |  1|x1   | 10|
  2|x2   |hz     |  2|x2   | 11|
  3|x3   |       |  3|x3   | 12|
  4|x4   |bj     |  4|x4   | 16|
  5|x5   |gz     |   |     |   |

右连接:RIGHT JOIN
同理右连接RIGHT JOIN就是求两个表的交集外加右表剩下的数据。再次从笛卡尔积的角度描述,右连接就是从笛卡尔积中挑出ON子句条件成立的记录,然后加上右表中剩余的记录

select 
a.*,
b.*
from testa as a 
right join testb as b  on a.aid=b.bid;

aid|aname|address|bid|bname|age|
---|-----|-------|---|-----|---|
  1|x1   |sh     |  1|x1   | 10|
  2|x2   |hz     |  2|x2   | 11|
  3|x3   |       |  3|x3   | 12|
  4|x4   |bj     |  4|x4   | 16|
   |     |       |  7|x7   | 19|
   |     |       |  8|x8   | 22|
   |     |       |  9|x9   | 24|
   |     |       | 10|x10  | 44|

SQL UNION 操作符合并两个或多个 SELECT 语句的结果
union all 结果不去重复
union去重复
注意:
1,名称是第一张表决定
2,生产尽量不用*
3,正常来说,对应字段类型保持一致,mysql发展到今时今日不同字段类型也可以识别出。

select 
a.*,
b.*
from testa as a 
left join testb as b  on a.aid=b.bid
union
select 
a.*,
b.*
from testa as a 
right join testb as b  on a.aid=b.bid;

aid|aname|address|bid|bname|age|
---|-----|-------|---|-----|---|
  1|x1   |sh     |  1|x1   | 10|
  2|x2   |hz     |  2|x2   | 11|
  3|x3   |       |  3|x3   | 12|
  4|x4   |bj     |  4|x4   | 16|
  5|x5   |gz     |   |     |   |
   |     |       |  7|x7   | 19|
   |     |       |  8|x8   | 22|
   |     |       |  9|x9   | 24|
   |     |       | 10|x10  | 44|

面试题:

  1. 查询出部门编号为30的所有员工的编号和姓名
select empno, empno, deptno from emp where deptno = 30;

empno|empno|deptno|
-----|-----|------|
 7499| 7499|    30|
 7521| 7521|    30|
 7654| 7654|    30|
 7698| 7698|    30|
 7844| 7844|    30|
 7900| 7900|    30|

2.找出部门编号为10中所有经理,和部门编号为20中所有销售员的详细资料。

select emp.* from emp where deptno = 10 and job = 'MANAGER'
union all 
select emp.* from emp where deptno = 20 and job = 'SALESMAN';

empno|ename|job    |mgr |hiredate           |sal    |comm|deptno|
-----|-----|-------|----|-------------------|-------|----|------|
 7782|CLARK|MANAGER|7839|1981-06-09 00:00:00|2450.00|    |    10|

3.查询所有员工详细信息,用工资降序排序,如果工资相同使用入职日期升序排序

select emp.* from emp order by (sal+ifNull(comm,0)) desc, hiredate asc;
empno|ename |job      |mgr |hiredate           |sal    |comm   |deptno|
-----|------|---------|----|-------------------|-------|-------|------|
 7839|KING  |PRESIDENT|    |1981-11-17 00:00:00|5000.00|       |    10|
 7902|FORD  |ANALYST  |7566|1981-12-03 00:00:00|3000.00|       |    20|
 7788|SCOTT |ANALYST  |7566|1982-12-09 00:00:00|3000.00|       |    20|
 7566|JONES |MANAGER  |7839|1981-04-02 00:00:00|2975.00|       |    20|
 7698|BLAKE |MANAGER  |7839|1981-05-01 00:00:00|2850.00|       |    30|
 7654|MARTIN|SALESMAN |7698|1981-09-28 00:00:00|1250.00|1400.00|    30|
 7782|CLARK |MANAGER  |7839|1981-06-09 00:00:00|2450.00|       |    10|
 7499|ALLEN |SALESMAN |7698|1981-02-20 00:00:00|1600.00| 300.00|    30|
 7521|WARD  |SALESMAN |7698|1981-02-22 00:00:00|1250.00| 500.00|    30|
 7844|TURNER|SALESMAN |7698|1981-09-08 00:00:00|1500.00|   0.00|    30|
 7934|MILLER|CLERK    |7782|1982-01-23 00:00:00|1300.00|       |    10|
 7876|ADAMS |CLERK    |7788|1983-01-12 00:00:00|1100.00|       |    20|
 7900|JAMES |CLERK    |7698|1981-12-03 00:00:00| 950.00|       |    30|
 7369|SMITH |CLERK    |7902|1980-12-17 00:00:00| 800.00|       |    20|

4.列出最低薪金大于1500的各种工作及从事此工作的员工人数。

select job, count(1) as "people count" from emp where (sal+ifNull(comm,0)) >1500 group by job;

job      |people count|
---------|------------|
ANALYST  |           2|
MANAGER  |           3|
PRESIDENT|           1|
SALESMAN |           3|

5.列出在销售部工作的员工的姓名,假定不知道销售部的部门编号。

select emp.ename from emp
inner join dept
on emp.deptno = dept.deptno
where dept.dname = 'SALES';

ename |
------|
ALLEN |
WARD  |
MARTIN|
BLAKE |
TURNER|
JAMES |

6.查询姓名以S开头的\以S结尾\包含S字符\第二个字母为L

select ename from emp
where ename like 'S%';

ename|
-----|
SMITH|
SCOTT|

select ename from emp
where ename like '%S';

ename|
-----|
JONES|
ADAMS|
JAMES|

select ename from emp
where ename like '%S%';

ename|
-----|
SMITH|
JONES|
SCOTT|
ADAMS|
JAMES|

select ename from emp
where ename like '_L%';

ename|
-----|
ALLEN|
BLAKE|
CLARK|

7.查询每种工作的最高工资、最低工资、人数

select job
,max(sal+ifNull(comm,0)) as maxSal
,min(sal+ifNull(comm,0)) as minSal
,count(1) as number
from emp
group by job;

job      |maxSal |minSal |number|
---------|-------|-------|------|
ANALYST  |3000.00|3000.00|     2|
CLERK    |1300.00| 800.00|     4|
MANAGER  |2975.00|2450.00|     3|
PRESIDENT|5000.00|5000.00|     1|
SALESMAN |2650.00|1500.00|     4|

8.列出薪金 高于 公司平均薪金的所有员工号,员工姓名,所在部门名称,上级领导,工资,工资等级

select 
emp.empno 
,emp.ename 
,dept.dname 
,emp.mgr 
,emp.sal+ifNull(emp.comm,0) as salary
,(select grade from salgrade where emp.sal+ifNull(emp.comm,0) >= losal and emp.sal+ifNull(emp.comm,0) <= hisal) as grade
from emp
left join dept
on emp.deptno = dept.deptno
where (emp.sal+ifNull(emp.comm,0)) > (select avg(emp.sal+ifNull(emp.comm,0)) from emp);

empno|ename |dname     |mgr |salary |grade|
-----|------|----------|----|-------|-----|
 7782|CLARK |ACCOUNTING|7839|2450.00|    4|
 7839|KING  |ACCOUNTING|    |5000.00|    5|
 7566|JONES |RESEARCH  |7839|2975.00|    4|
 7788|SCOTT |RESEARCH  |7566|3000.00|    4|
 7902|FORD  |RESEARCH  |7566|3000.00|    4|
 7654|MARTIN|SALES     |7698|2650.00|    4|
 7698|BLAKE |SALES     |7839|2850.00|    4|
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值