SQL面试题:求时间差之和(有重复不计)
程序员文章站
2022-06-07 10:01:08
面试某某公司bi岗位的时候,面试题中的一道sql题,咋看一下很简单,写的时候发现自己缺乏总结,没有很快的写出来。
题目如下:
求每个品牌的促销天数
表sale为促销营...
面试某某公司bi岗位的时候,面试题中的一道sql题,咋看一下很简单,写的时候发现自己缺乏总结,没有很快的写出来。
题目如下:
求每个品牌的促销天数
表sale为促销营销表,数据中存在日期重复的情况,例如id为1的end_date为20180905,id为2的start_date为20180903,即id为1和id为2的存在重复的销售日期,求出每个品牌的促销天数(重复不算)
表结果如下:
+------+-------+------------+------------+ | id | brand | start_date | end_date | +------+-------+------------+------------+ | 1 | nike | 2018-09-01 | 2018-09-05 | | 2 | nike | 2018-09-03 | 2018-09-06 | | 3 | nike | 2018-09-09 | 2018-09-15 | | 4 | oppo | 2018-08-04 | 2018-08-05 | | 5 | oppo | 2018-08-04 | 2018-08-15 | | 6 | vivo | 2018-08-15 | 2018-08-21 | | 7 | vivo | 2018-09-02 | 2018-09-12 | +------+-------+------------+------------+
最终结果应为
brand | all_days |
---|---|
nike | 13 |
oppo | 12 |
vivo | 18 |
建表语句
-- ---------------------------- -- table structure for sale -- ---------------------------- drop table if exists `sale`; create table `sale` ( `id` int(11) default null, `brand` varchar(255) default null, `start_date` date default null, `end_date` date default null ) engine=innodb default charset=utf8; -- ---------------------------- -- records of sale -- ---------------------------- insert into `sale` values (1, 'nike', '2018-09-01', '2018-09-05'); insert into `sale` values (2, 'nike', '2018-09-03', '2018-09-06'); insert into `sale` values (3, 'nike', '2018-09-09', '2018-09-15'); insert into `sale` values (4, 'oppo', '2018-08-04', '2018-08-05'); insert into `sale` values (5, 'oppo', '2018-08-04', '2018-08-15'); insert into `sale` values (6, 'vivo', '2018-08-15', '2018-08-21'); insert into `sale` values (7, 'vivo', '2018-09-02', '2018-09-12');
方式1:
利用自关联下一条记录的方法
select brand,sum(end_date-befor_date+1) all_days from ( select s.id , s.brand , s.start_date , s.end_date , if(s.start_date>=ifnull(t.end_date,s.start_date) ,s.start_date,date_add(t.end_date,interval 1 day) ) as befor_date from sale s left join (select id+1 as id ,brand,end_date from sale) t on s.id = t.id and s.brand = t.brand order by s.id )tmp group by brand
运行结果
+-------+---------+ | brand | all_day | +-------+---------+ | nike | 13 | | oppo | 12 | | vivo | 18 | +-------+---------+
该方法对本题中的表格有效,但对于有id不连续的品牌的记录时不一定适用。
方式2:
select a.brand,sum( case when a.start_date=b.start_date and a.end_date=b.end_date and not exists( select * from sale c left join sale d on c.brand=d.brand where d.brand=a.brand and c.start_date=a.start_date and c.id<>d.id and (d.start_date between c.start_date and c.end_date and d.end_date>c.end_date or c.start_date between d.start_date and d.end_date and c.end_date>d.end_date) ) then (a.end_date-a.start_date+1) when (a.id<>b.id and b.start_date between a.start_date and a.end_date and b.end_date>a.end_date ) then (b.end_date-a.start_date+1) else 0 end ) as all_days from sale a join sale b on a.brand=b.brand group by a.brand
运行结果
+-------+----------+ | brand | all_days | +-------+----------+ | nike | 13 | | oppo | 12 | | vivo | 18 | +-------+----------+
其中条件
d.start_date between c.start_date and c.end_date and d.end_date>c.end_date or c.start_date between d.start_date and d.end_date and c.end_date>d.end_date
可以换成
c.start_date < d.end_date and (c.end_date > d.start_date)
结果同样正确
用分析函数同样可行的,自己电脑暂时没装oracle,用的mysql写的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。