一、题目

1.第一题:按transaction_type分组,如何通过查询方式输出每组中transaction_amount最大的前三行记录。

mysql计算本月发放数量_创建表

2.第二题:

  • 统计各部门的部门名称,实发工资总和,平均工资。
  • 查询实际月收入比销售部门所有员工基本工资都高的雇员姓名

3.第三题:利用表1、表2、表3经过处理, 形成表4。表4中TYPE字段的要求:根据贷款逾期天数定义贷款类型(如果贷款逾期天数等于0则贷款类型为CURRENT;如果贷款逾期天数大于0且小于等于89则贷款类型为MIDDLE;如果贷款逾期天数大于等于90则贷款类型为CHRGO)。

mysql计算本月发放数量_mysql计算本月发放数量_02


mysql计算本月发放数量_mysql计算本月发放数量_03


mysql计算本月发放数量_建表_04


mysql计算本月发放数量_mysql计算本月发放数量_05

4.第四题:

  • 查询出sno,cno重复的数据;
  • 查询sno,cno,score都重复的数据,且除id最小的一条数据外

5.第五题:数据库中有中国区域表,表名dicarea,字段有id(主键)、areaid(区域代码),parentid(父区域ID),area_level(区域级别:1=省,2=市,3=县),请现实以下查询结果:

mysql计算本月发放数量_数据_06


mysql计算本月发放数量_创建表_07

6.第六题:

  • 计算2017年每笔投资均大于50万的用户;
  • 计算2017年仅投资过CFH和AX产品的用户;
  • 计算归属于10002业务员的投资金额。

7.第七题:

  • 找出订单金额大于5000的客户,年龄区间在0-25,25-45,45岁以上的客户有多少,区间均为前闭后开。
  • 限制男性客户,取每个男性客户的第一次订单时间,及对应的订单金额。
  • 取不同性别中,累计订单金额TOP2的客户。

8.第八题:查询出电信中几大产品出账都小于75元的客户名称

mysql计算本月发放数量_mysql_08

9.第九题:请查询出应还月份,逾期1天以上(>=1),30天以上(>=30),60天以上的数量(>=60):

mysql计算本月发放数量_数据_09


要求查询结果如下(格式一样就行,下表的结果有问题):

mysql计算本月发放数量_mysql_10

二、解题思路

1.第一题

# 建表
create table transaction(id int,
transaction_type char,
transaction_amount int);


# 插入值
insert into transaction values
(1,'a',2),
(2,'a',3),
(3,'a',3),
(4,'a',1),
(5,'b',8),
(6,'b',9),
(7,'b',1),
(8,'b',9),
(9,'b',5);


 # 解题思路:
# 方法一:使用窗口函数
select * from(
    select *,row_number() over(partition by transaction_type order by transaction_amount desc) 组内排名
    from transaction) t
where 组内排名 <= 3;


# 方法二:关联子查询
select * from transaction a
where (select count(*) from transaction b where b.transaction_amount > a.transaction_amount
        and b.transaction_type = a.transaction_type) <= 2;

2.第二题:

# 建立雇员表
create table employee
(
empid varchar(10) primary key,
name varchar(10) not null,
gender varchar(6) not null,
title varchar(20),
birthday date,
depid varchar(6)
);


# 建立部门表
create table department
(
depid varchar(6) primary key,
depname varchar(20)
);


# 创建工资表
create table salary
(
empid varchar(10) primary key,
base_salary decimal(10,2),
title_salary decimal(10,2),
deduction decimal(10,2)
);


# 统计各部门的部门名称,实发工资总和,平均工资
select d.depname 部门名称, sum(s.base_salary + s.title_salary) 实发工资总和,
avg(s.base_salary + s.title_salary - s.deduction) 平均工资
from 
department d left join employee e on d.depid = e.depid
	     left join salary s on s.empid = e.empid
group by d.depid;


# 查询实际月收入比销售部门所有员工基本工资都高的雇员姓名
select e.name 雇员姓名, 
(s.base_salary + s.title_salary - s.deduction) 实际月收入 
from 
employee e left join salary s on e.empid = s.empid
           left join department d on e.depid = d.depid
where (s.base_salary + s.title_salary - s.deduction) > all(select s1.base_salary 
							   from employee e1, salary s1, department d1
                                                           where e1.empid = s1.empid and e1.depid = d1.depid
                                                           and d1.depname = '销售部');

3.第三题:

# 创建表1
create table a1
(
loan_no varchar(20) primary key,
id_no char not null,
actv_dt date
);


insert into a1
values('1000114260','1','2011-06-07'),
('1000143723','2','2011-09-21'),
('1000162024','3','2011-12-09'),
('1000174934','4','2012-03-23'),
('1000182256','5','2012-05-15');


# 创建表2
create table a2
(
loan_no varchar(20) primary key,
od_days int(6)
);


insert into a2
values('1000114260',90),
('1000174934',16),
('1000182256',0),
('1000143723',45),
('1000162024',3);


# 创建表3
create table a3
(
id_no char not null,
lim int(10) not null,
outstanding int(10) not null
);


insert into a3
values('5',30000,25110),
('2',40000,45000),
('2',50000,56000),
('2',45000,45000),
('1',15000,6378),
('1',80000,60395),
('3',60000,57773),
('4',30000,28656),
('4',30000,10000);


# 利用表1,2,3创建表4
create table a4
select a1.loan_no as LOAN_NO, a1.id_no as ID_NO, a1.actv_dt as ACTV_DT,
a2.od_days as OD_DAYS, 
if(a2.od_days = 0, 'CURRENT', if(a2.od_days between 0 and 89,'MIDDLE','CHRGO')) as TYPE,
sum(a3.lim) as LIM, sum(a3.outstanding) as OUTSTANDING
from a1 inner join a2 on a1.loan_no = a2.loan_no
	inner join a3 on a3.id_no = a1.id_no
group by a1.id_no, a1.loan_no;

4.第四题:

# 建表
create table t_1
(
id int primary key auto_increment,
sno int(5),
cno int,
score int(5)
);


# 插入数据
insert into t_1
values(1,1001,1,89),
(2,1001,1,89),
(3,1002,1,87),
(4,1002,1,90),
(5,1003,1,86);


# 查询出sno,cno重复的数据
select * from t_1
where (sno,cno) in (select sno,cno
		    from t_1
	            group by sno,cno
	            having count(*) >= 2);


# 查询sno,cno,score都重复的数据,且除id最小的一条数据外
select * from t_1
where (sno,cno,score) in 
(select sno,cno,score from t_1 group by sno,cno,score having count(*) >= 2) 
and id not in (select min(id) from t_1);

5.第五题:

# 建表
create table dic_area(
id int,
area_id int,
area_name varchar(15),
parented int,
area_level int(1));


# 插入数据
insert into dic_area values
(1,130000,"河北省",100000,1),
(2,130100,"石家庄市",130000,2),
(3,130102,"长安区",130100,3),
(4,130104,"桥西区",130100,3);


# 查询结果
select sheng.area_id 省代码,sheng.area_name 省名称,shi.area_id 市代码,shi.area_name 市名称,xian.area_id 县代码,xian.area_name 县名称
from (select area_id,area_name,parented from dic_area where area_level=1) sheng
left join (select area_id,area_name,parented from dic_area where area_level=2) shi
on sheng.area_id = shi.parented
left join (select area_id,area_name,parented from dic_area where area_level=3) xian
on shi.area_id = xian.parented;

6.第六题:

# 创建投资表
create table invest(
created_at datetime,
user_id char(4),
invest_item varchar(10),
invest_amount decimal(38,10));


# 创建业务员表
create table dim(
user_id char(4),
start_date datetime,
end_date datetime,
agent_id char(5));


# 插入投资表数据
insert into invest values
('2017-11-01 01:32:00','A123','CFH','100000'),
('2017-12-05 03:42:00','A123','AX','450000'),
('2017-12-11 17:42:00','A123','CH','700000'),
('2017-12-06 20:06:00','B456','CFH','1500000'),
('2017-12-26 14:36:00','B456','AX','800000'),
('2018-01-06 14:36:00','C789','JUIN','300000');


# 插入业务员表数据
insert into dim values
('A123','2016-01-01 00:00:00','2017-12-04 23:59:59','10001'),
('A123','2017-12-05 00:00:00','3001-12-31 23:59:59','10002'),
('B456','2015-10-31 00:00:00','2016-12-15 23:59:59','10001'),
('B456','2016-12-16 00:00:00','3001-12-31 23:59:59','10003'),
('C789','2015-01-01 00:00:00','3001-12-31 23:59:59','10002');


# 计算2017年每笔投资均大于50万的用户
select distinct user_id
from invest
where invest_amount > 500000 and created_at between '2017-01-01' and '2017-12-31';


# 计算2017年仅投资过CFH和AX的用户
select a.user_id
from (select user_id from invest where invest_item = 'CFH' and year(created_at) = '2017') a 
inner join (select user_id from invest where invest_item = 'AX' and year(created_at) = '2017') b on a.user_id = b.user_id
where a.user_id not in (select user_id from invest where invest_item not in ('CFH','AX') and year(created_at) = '2017');


# 计算归属于10002业务员的投资金额
select agent_id, sum(invest_amount) 投资金额
from dim d left join invest i 
on d.user_id = i.user_id and i.created_at between d.start_date and d.end_date
where agent_id = 10002
group by agent_id;

7.第七题:

# 建表A
create table a
(
id bigint,
orderno varchar(10),
orderdate datetime,
price int
);

insert into a values
(01,01,'2019-6-11',6000),
(01,02,'2019-6-12',8000),
(02,03,'2019-6-11',5000),
(03,04,'2019-6-11',7000),
(04,05,'2019-6-11',3000),
(04,06,'2019-6-12',9000);

create table b
(
id bigint,
sex varchar(5),
age int
);

insert into b values
(01,'男',20),
(02,'男',50),
(03,'女',20),
(04,'男',42);


# 找出订单金额大于5000的客户,年龄区间在0-25,25-45,45岁以上的客户有多少
select sum(case when age < 25 then 1 else 0 end) as '25岁以下',
sum(case when age>=25 and age<45 then 1 else 0 end) as '年龄[25,45)',
sum(case when age >= 45 then 1 else 0 end) as '45岁以上'
from b
where id in (select distinct id from a where price>5000);


# 取每个男性客户的第一次订单时间以及对应的订单金额
select a.id,orderdate,price
from a inner join b on a.id = b.id
where sex = '男'
group by a.id;

# 如果报错ERROR 1055,原因是默认设置了ONLY_FULL_GROUP_BY,可以通过更改设置解决
select @@sql_mode;
set sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';


# 取不同性别中,累计订单金额Top2的客户
select id,sex,sums from 
(select a.id,sex,sum(price) as sums from a left join b on a.id = b.id group by a.id) a1
where (select count(*) from 
	  (select a.id,sex,sum(price) as sums from a left join b on a.id = b.id group by a.id) b1
	   where a1.sex=b1.sex and a1.sums<b1.sums)<2;

8.第八题:

# 建表
create table table0
(
name varchar(5),
prod varchar(5),
arpu int(5)
);

insert into table0
values('孙悟空','移动',73),
('孙悟空','宽带',82),
('猪八戒','移动',65),
('猪八戒','宽带',72),
('沙僧','移动',58),
('沙僧','宽带',120),
('沙僧','固话',19);


# 查询出电信中几大产品出账都小于75元的客户名称
# 客户购买产品的数量
select name,count(*) num_pro
from table0
group by name;

# 客户购买产品低于75元的个数
select name,count(*) num_less
from table0
where arpu < 75
group by name;

# 算出结果
select a.name
from (select name,count(*) num_pro from table0 group by name) a
inner join (select name,count(*) num_less from table0 where arpu < 75 group by name) b
on a.name = b.name
where a.num_pro = b.num_less;

9.第九题:

# 建表
create table pay(
ID int primary key auto_increment,
times date,
overdue int);

insert into pay(times,overdue) values
('2017/8/1',1),
('2017/6/3',6),
('2017/4/1',7),
('2017/8/2',30),
('2017/5/4',62),
('2017/3/2',78),
('2017/4/15',45);


# 查询结果
select date_format(times,'%Y-%m') 应还日期,
sum(case when overdue>=1 and overdue<30 then 1 else 0 end) '逾期1天以上',
sum(case when overdue>=30 and overdue<60 then 1 else 0 end) '逾期30天以上',
sum(case when overdue>=60 then 1 else 0 end) '逾期60天以上'
from pay
group by date_format(times,'%Y-%m');