面试某某公司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');

利用自关联下一条记录的方法

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 |+-------+---------+

方式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写的。

更多相关文章

  1. Android: Linear Layout and weight
  2. Scala 两数之和
  3. 数组的一些基本函数
  4. 我的第八个代码
  5. android实现双击事件监听
  6. Android中防止重复点击的小技巧
  7. 自定义定时器
  8. android 双击事件监听
  9. android获取时间差的方法

随机推荐

  1. 注册中心 Eureka源码解析 —— 应用实例
  2. 老艿艿说:关于时间管理的分享
  3. 分布式作业系统 Elastic-Job-Lite 源码分
  4. 如何使用Python实现FTP服务器?Python学习
  5. CentOS7 上搭建多节点 Elasticsearch集群
  6. 分布式做系统 Elastic-Job-Lite 源码分析
  7. yarn-site.xml的部分资源配置参数,主要是
  8. 注册中心 Eureka 源码解析 —— 任务批处
  9. 分布式作业系统 Elastic-Job-Cloud 源码
  10. 分布式作业 Elastic-Job-Lite 源码分析