面試某某公司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寫的。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。
新聞熱點
疑難解答