当前位置: 首页 > 编程笔记 >

SQL面试题:求时间差之和(有重复不计)

越勇
2023-03-14
本文向大家介绍SQL面试题:求时间差之和(有重复不计),包括了SQL面试题:求时间差之和(有重复不计)的使用技巧和注意事项,需要的朋友参考一下

面试某某公司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写的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。

 类似资料:
  • 我注意到以下代码在netbeans中是完全合法的: 然而eclipse对此并不满意,我必须这样初始化它: 有趣的是netbean建议不要在初始化部分指定类型参数,而是使用菱形运算符??我想知道这两种方法之间的区别。以及应该使用哪一种,这样代码就可以在不同的IDE中使用而不会有任何变化。

  • 我想知道更多处理数组的numpy。我发现a[:,None]和a[:,]之间是不同的。我想深入研究何时何地使用它们。 我试图以特殊的方式解决从2d数组中减去1d的问题,就像numpy-subtract-add-1d-array-from-2d-array一样,我意识到a[:,None]和a[:,]是不同的。 有人能给我关于它的官方或具体参考吗?我真的会很感激你的!

  • 发送表单数据时使用命令名称和模型属性有什么区别? 和 我应该在哪个时间点使用它们中的任何一个?

  • 可能重复: 何时使用LinkedList 我应该什么时候使用arrayList,什么时候使用LinkedList? 什么时候应该使用,和?

  • 我是Java和静态编程语言的新手。 最近当我在学习静态编程语言的时候读了一个教程。 我发现有一些让我困惑。 、和

  • 我们如何将下面的代码转换为工厂而不是服务 在这两个方面,工厂和服务的更好实施方式是什么,请提出建议。我是AngularJs的新手,所以请帮我解决这个问题