sql面试题20200607
以下是数据库中 4 个表的表结构:
表一:订单表(表名:table_order),主键是order_id+goods_id,用于记录每个订单的商品明细。同一个订单可能有多个商品,每条信息记录每个订单里不同商品的件单价和销售件数等,销售额=件单价price*销售件amount
order_id | user_id | goods_id | add_time | price | amount | department_id |
---|---|---|---|---|---|---|
1236 | 111 | 20340 | 2014/3/22 1:19 | 398.00 | 1 | 1 |
1236 | 111 | 12432 | 2014/3/22 1:19 | 18.00 | 2 | 2 |
1648 | 333 | 56235 | 2014/4/11 21:00 | 399.00 | 3 | 3 |
1648 | 333 | 42521 | 2014/4/11 21:00 | 290.00 | 1 | 4 |
1648 | 333 | 24466 | 2014/4/11 21:00 | 279.00 | 2 | 1 |
2060 | 222 | 25948 | 2014/3/30 13:21 | 190.00 | 2 | 2 |
2472 | 222 | 20942 | 2014/4/22 9:59 | 380.00 | 1 | 3 |
2472 | 222 | 98303 | 2014/4/22 9:59 | 299.00 | 1 | 4 |
2472 | 222 | 39555 | 2014/4/22 9:59 | 848.00 | 2 | 4 |
2884 | 444 | 20249 | 2014/5/7 17:53 | 599.00 | 1 | 2 |
2884 | 444 | 39523 | 2014/5/7 17:53 | 699.00 | 1 | 2 |
备注:order_id:订单号,add_time:下单时间,user_id:客户号,goods_id:商品编号,price:件单价,amount:销售件数,department_id:品类编号
表二:品类表(表名:table_department),主键是department_id。
department_id | department_name |
---|---|
1 | 女装 |
2 | 女鞋 |
3 | 男装 |
4 | 男鞋 |
表三:客户表(表名:table_user),主键是user_id。
user_id | user_name |
---|---|
111 | 张敏 |
222 | 黎佳 |
333 | 杨峰 |
444 | 催楠 |
备注:user_id:客户号,user_name:客户姓名
表:购物车表(表名:table_cart),主键是user_id+goods_id+add_time,用于记录客户不同时点放入购物车的商品情况(商品ID、商品数量、商品删除时间、商品购买时间)
user_id | goods_id | amount | add_time | delete_time | buy_time |
---|---|---|---|---|---|
111 | 56235 | 2 | 2014/10/22 10:01 | 2014/10/22 10:20 | |
111 | 24466 | 1 | 2014/10/22 10:21 | 2014/10/22 10:29 | |
111 | 25948 | 3 | 2014/10/22 10:24 | ||
111 | 39555 | 1 | 2014/10/22 21:20 | 2014/10/22 21:26 | |
111 | 98303 | 4 | 2014/10/22 21:24 | ||
111 | 20249 | 2 | 2014/10/22 21:39 |
备注:客户主动删除商品或购买商品,时间分别记录在delete_time和buy_time两个字段,否则记录为空
请在25 分钟内完成下面4 道试题:
1:请写出“计算2014/03/22-2014/04/30 每天的购买客户数、订单量、销售件数、销售额”的
SQL 代码,结果格式要求如下:
日期 | 购买客户数 | 订单量 | 销售件数 | 销售额 |
---|---|---|---|---|
2014/3/22 | 1 | 1 | 3 | 434 |
2014/3/30 | 1 | 1 | 2 | 380 |
2014/4/11 | 1 | 1 | 6 | 2,045 |
2014/4/22 | 1 | 1 | 4 | 2,375 |
2:请写出“计算2014 年4 月各品类的销售额、晚上20-24 点销售额”的SQL 代码,结果格式
要求如下:
品类 | 销售额 | 20-24点销售额 |
---|---|---|
女装 | 558 | 558 |
男装 | 1,577 | 1,197 |
男鞋 | 2,285 | 290 |
3:请写出“提取2014 年3-5 月销售额排名前三的客户信息(排名/客户号/客户姓名/总销售额
/购买品类)”的SQL 代码,结果格式要求如下:
排名 | 客户号 | 客户姓名 | 总销售额 | 购买品类 |
---|---|---|---|---|
1 | 222 | 黎佳 | 2,755 | 女鞋、男装、男鞋 |
2 | 333 | 杨峰 | 2,045 | 女装、男装、男鞋 |
3 | 444 | 催楠 | 1,298 | 女鞋 |
4:特卖模式下,客户把商品放入购物车后,需在 20 分钟内完成购买,每加入一件新的商品,购物时长(即 20 分钟)将重新计算,若在 20 分钟内无放入购物车行为,购物车内商品会由系统自动释放。请结合购物车表的数据结构,写出计算 2014 年 3 月每日平均每件商品 hold 货时长(即商品的锁定时间)的逻辑和 SQL 代码,结果格式要求如下:
日期 | 平均hold货时长 |
---|---|
2014/3/1 | |
2014/3/2 | |
…… |
$ vi create_table.sql
编辑保存如下内容:
--订单表
drop table if exists table_order;
create table table_order(
order_id string
, user_id string
, goods_id string
, add_time timestamp
, price decimal(32,2)
, amount int
, department_id string
) row format delimited fields terminated by '\t';
insert into table_order values ('1236','111','20340','2014-03-22 01:19:00',398.00,1,'1');
insert into table_order values ('1236','111','12432','2014-03-22 01:19:00',18.00 ,2,'2');
insert into table_order values ('1648','333','56235','2014-04-11 21:00:00',399.00,3,'3');
insert into table_order values ('1648','333','42521','2014-04-11 21:00:00',290.00,1,'4');
insert into table_order values ('1648','333','24466','2014-04-11 21:00:00',279.00,2,'1');
insert into table_order values ('2060','222','25948','2014-03-30 13:21:00',190.00,2,'2');
insert into table_order values ('2472','222','20942','2014-04-22 09:59:00',380.00,1,'3');
insert into table_order values ('2472','222','98303','2014-04-22 09:59:00',299.00,1,'4');
insert into table_order values ('2472','222','39555','2014-04-22 09:59:00',848.00,2,'4');
insert into table_order values ('2884','444','20249','2014-05-07 17:53:00',599.00,1,'2');
insert into table_order values ('2884','444','39523','2014-05-07 17:53:00',699.00,1,'2');
--品类表
drop table if exists table_department;
create table table_department(
department_id string
, department_name string
) ;
insert into table_department values ('1','女装');
insert into table_department values ('2','女鞋');
insert into table_department values ('3','男装');
insert into table_department values ('4','男鞋');
--客户表
drop table if exists table_user;
create table table_user (
user_id string
, user_name string
);
insert into table_user values('111','张敏');
insert into table_user values('222','黎佳');
insert into table_user values('333','杨峰');
insert into table_user values('444','催楠');
--购物车表
drop table if exists table_cart;
create table table_cart(
user_id string
, goods_id string
, amount int
, add_time timestamp
, delete_time timestamp
, buy_time timestamp
);
insert into table table_cart values ('111','56235',2,'2014-10-22 10:01:00',null,'2014-10-22 10:20:00');
insert into table table_cart values ('111','24466',1,'2014-10-22 10:21:00','2014-10-22 10:29:00',null);
insert into table table_cart values ('111','25948',3,'2014-10-22 10:24:00',null,null);
insert into table table_cart values ('111','39555',1,'2014-10-22 21:20:00','2014-10-22 21:26:00',null);
insert into table table_cart values ('111','98303',4,'2014-10-22 21:24:00',null,null);
insert into table table_cart values ('111','20249',2,'2014-10-22 21:39:00',null,null);
$ hive -f create_table.sql
执行建表导数脚本
–1.计算 2014/03/22-2014/04/30 每天的购买客户数、订单量、销售件数、销售额
select
count(distinct user_id) as user_id_num
,count(distinct order_id) as order_id_num
,sum(amount) as amount_num
,sum(price*amount) as total_price
from
table_order
where date(add_time)
between '2014-03-22' and '2014-04-30';
查询结果
user_id_num | order_id_num | amount_num | total_price |
---|---|---|---|
3 | 4 | 15 | 5234 |
–2.计算 2014 年 4 月各品类的销售额、晚上 20-24 点销售额
select
b.department_name as department_name
, sum(a.price*a.amount) as total_sale
, sum(if(hour(a.add_time) between 20 and 24,a.price*a.amount,0)) as evening_total_sale
from
table_order a
join table_department b
on a.department_id = b.department_id
group by b.department_name;
查询结果
department_name | total_sale_price | evening_total_sale |
---|---|---|
女装 | 956 | 558 |
女鞋 | 1714 | 0 |
男装 | 1577 | 1197 |
男鞋 | 2285 | 290 |
–提取 2014 年 3-5 月销售额排名前三的客户信息(排名/客户号/客户姓名/总销售额/购买品类)
select
t1.rn as rn
, t1.user_id as user_id
, t2.user_name as user_name
, t1.total_sale as total_sale
, t1.department_name_col as department_name_col
from
(select
a.user_id
, sum(price*amount) as total_sale
, concat_ws('、',collect_set(b.department_name)) AS department_name_col
, row_number() over(order by sum(price*amount) desc) as rn
from
table_order a
left join table_department b
on a.department_id = b.department_id
group by
a.user_id
) t1 --通过客户id将品类数据行转列
left join table_user t2 --取客户名称
on t1.user_id = t2.user_id
where t1.rn <= 3;
查询结果
–计算 2014 年 3 月每日平均每件商品 hold 货时长(即商品的锁定时间)
select
to_date(add_time) as dt
, sum(duration_time)/(count(1)*60.00) as per_duration_min --平均时长(分钟)
from
(select
add_time
, unix_timestamp(coalesce(delete_time,buy_time,each_end_time)) - unix_timestamp(add_time) as duration_time -- 每条的时长
from
(select
user_id
, add_time
, delete_time
, buy_time
, min(cast(end_time as timestamp)) over(partition by user_id order by add_time desc rows between unbounded preceding and current row) as each_end_time --取每批的自动清空时间
from
(
select
user_id
, add_time
, delete_time
, buy_time
, case when unix_timestamp(next_time) - unix_timestamp(add_time) > 20*60 or next_time is null then from_unixtime(unix_timestamp(add_time)+ 20*60) end as end_time --只对分组最后一条打上结束时间
from
(select
user_id
, add_time
, delete_time
, buy_time
, lead(add_time) over(partition by user_id order by add_time) as next_time --下一条商品加入时间
from table_cart
) t1
)t2
)t3
)t4
group by to_date(add_time);
查询结果
dt | per_duration |
---|---|
2014/10/22 | 18 |