当前位置: 首页 > 面试题库 >

查找特定用户MySQL在同一张表中的日期范围重叠

严令秋
2023-03-14
问题内容

我绝不是MySQL专家,所以我正在寻求有关此问题的任何帮助。

我需要执行一个简单的测试(原则上),我有这个(简化的)表:

tableid | userid  | car      | From        | To
--------------------------------------------------------
1       | 1       |  Fiesta  |  2015-01-01 | 2015-01-31
2       | 1       |  MX5     |  2015-02-01 | 2015-02-28
3       | 1       |  Navara  |  2015-03-01 | 2015-03-31
4       | 1       |  GTR     |  2015-03-28 | 2015-04-30
5       | 2       |  Focus   |  2015-01-01 | 2015-01-31
6       | 2       |  i5      |  2015-02-01 | 2015-02-28
7       | 2       |  Aygo    |  2015-03-01 | 2015-03-31
8       | 2       |  206     |  2015-03-29 | 2015-04-30
9       | 1       |  Skyline |  2015-04-29 | 2015-05-31
10      | 2       |  Skyline |  2015-04-29 | 2015-05-31

我需要在这里找到两件事:

  1. 如果任何用户的汽车任务中有日期重叠超过一天(任务结束可以与新任务开始的同一天)。
  2. 是否有两个用户试图在同一日期分配相同的汽车,或者他们在同一汽车上的日期范围重叠。

因此,我正在寻找的查询(或多个查询)应返回这些行:

tableid | userid  | car      | From        | To
--------------------------------------------------------
3       | 1       |  Navara  |  2015-03-01 | 2015-03-31
4       | 1       |  GTR     |  2015-03-28 | 2015-04-30
7       | 2       |  Aygo    |  2015-03-01 | 2015-03-31
8       | 2       |  206     |  2015-03-29 | 2015-04-30
9       | 1       |  Skyline |  2015-04-29 | 2015-05-31
10      | 2       |  Skyline |  2015-04-29 | 2015-05-31

我觉得我在这里碰壁,我很高兴能够在单独的查询中进行这些比较。我需要将它们显示在一个表中,但是我总是可以将结果合并。

我已经进行了研究,并进行了数小时的测试,但无法达到想要的结果。

SQLFiddle与上面的测试数据

我已经尝试过这些帖子(它们并不是我所需要的,但是足够接近,或者我认为):

比较同一表格中的两个日期范围

如何比较同一表中文本列的值

这是我能找到的最接近的解决方案,但是当我在单个表(将表连接到自身)上尝试时,我得到了疯狂的结果:检查表是否存在时间重叠?

编辑

作为临时解决方案,我采用了另一种方法,类似于我在研究中发现的帖子(上)。现在,我将检查新租车/转让日期是否与表格中的任何日期范围重叠。如果是这样,我将保存与日期重叠的行的ID。这样,至少我将能够标记重叠并允许用户查看标记的行并手动解决任何重叠。

感谢所有为此提供帮助的人,除非有人有更好的方法来实现,否则我将在接下来的24小时内将philipxy答案标记为已选择的答案。我毫不怀疑,按照他的回答,我最终将能够达到我所需要的结果。目前,我需要采用任何可行的解决方案,因为我需要在接下来的几天中完成我的项目,因此改变了方法。

编辑#2

这两个答案都很出色,对于发现这篇文章与我有同样问题的人,阅读它们并看看小提琴!:)许多惊人的脑力劳动进入了他们!暂时,我不得不采用在我的#1编辑中提到的解决方案,但是我将通过@Ryan
Vincent方法+ @philipxy编辑/注释来适应我的查询,以忽略最初的一天重叠。


问题答案:

这是第一部分:每个用户的汽车重叠…

SQLFiddle-相关查询和联接查询

第二部分-
同一辆车同时使用多个用户:SQLFiddle相关查询和Join查询。在下面查询…

我使用相关查询:

您可能需要在userid和’car’上建立索引。但是-请检查“解释计划”以查看mysql如何访问数据。并尝试一下:)

每位使用者重叠的汽车

查询:

SELECT `allCars`.`userid`  AS `allCars_userid`, 
       `allCars`.`car`     AS `allCars_car`, 
       `allCars`.`From`    AS `allCars_From`, 
       `allCars`.`To`      AS `allCars_To`,
       `allCars`.`tableid` AS `allCars_id`
 FROM  
       `cars` AS `allCars`
 WHERE 
     EXISTS  
         (SELECT 1       
          FROM `cars` AS `overlapCar`            
          WHERE 
               `allCars`.`userid` = `overlapCar`.`userid` 
           AND `allCars`.`tableid` <> `overlapCar`.`tableid`          
           AND NOT (   `allCars`.`From`  >= `overlapCar`.`To`      /* starts after outer ends  */  
                    OR `allCars`.`To`    <= `overlapCar`.`From`))  /* ends before outer starts */
 ORDER BY
        `allCars`.`userid`, 
        `allCars`.`From`, 
        `allCars`.`car`;

结果:

allCars_userid  allCars_car  allCars_From  allCars_To  allCars_id  
--------------  -----------  ------------  ----------  ------------
             1  Navara       2015-03-01    2015-03-31             3
             1  GTR          2015-03-28    2015-04-30             4
             1  Skyline      2015-04-29    2015-05-31             9
             2  Aygo         2015-03-01    2015-03-31             7
             2  206          2015-03-29    2015-04-30             8
             2  Skyline      2015-04-29    2015-05-31            10

为什么有效? 或我的想法:

我使用相关查询,因此没有重复项,这对我来说可能是最容易理解的。还有其他表达查询的方式。每个都有优点和缺点。我想要一些我容易理解的东西。

要求:对于每个用户,请确保他们没有同时拥有两辆或更多辆汽车。

因此,对于每个用户记录(AllCars)检查完整表(overlapCar),看看是否能找到一个 不同的
记录是当前记录的时间重叠。如果找到一个,则选择我们正在检查的当前记录(在allCars中)。

因此, 重叠 检查为:

  • allCars useridoverLap userid必须是相同的
  • allCars汽车记录和overlap车记录 必须是不同的
  • allCars时间范围和overLap时间范围必须重叠。

时间范围检查:

不用检查重叠时间,而使用正面测试。最简单的方法是检查它是否重叠,然后对其应用a NOT

一辆汽车同时有多个用户…

查询:

SELECT  `allCars`.`car`     AS `allCars_car`,
        `allCars`.`userid`  AS `allCars_userid`,  
        `allCars`.`From`    AS `allCars_From`, 
        `allCars`.`To`      AS `allCars_To`, 
        `allCars`.`tableid` AS `allCars_id`

 FROM  
       `cars` AS `allCars`
 WHERE 
     EXISTS  
        (SELECT 1       
         FROM `cars` AS `overlapUser`            
         WHERE 
              `allCars`.`car` = `overlapUser`.`car` 
          AND `allCars`.`tableid` <> `overlapUser`.`tableid`          
          AND NOT (    `allCars`.`From`  >= `overlapUser`.`To`       /* starts after outer ends  */  
                   OR  `allCars`.`To`    <= `overlapUser`.`From`))  /* ends before outer starts */
 ORDER BY
        `allCars`.`car`,      
        `allCars`.`userid`, 
        `allCars`.`From`;

结果:

allCars_car  allCars_userid  allCars_From  allCars_To    allCars_id  
-----------  --------------  ------------  ----------  ------------
Skyline                   1  2015-04-29    2015-05-31             9
Skyline                   2  2015-04-29    2015-05-31            10

编辑:

鉴于@philipxy的评论,关于需要“大于或等于”检查的时间范围,我在这里更新了代码。我没有改变SQLFiddles



 类似资料:
  • 问题内容: 我试图找到一种基于特定列(id)在数据框中查找重叠数据范围(每行提供的开始/结束日期)的更有效方法。 数据框在“来自”列上排序 我认为有一种方法可以像我一样避免“双重”应用功能… 我使用“应用”功能在所有组上循环,并且在每个组中,每行使用“应用”: 问题答案: 您可以移动列并直接减去日期时间。 分组时应用它可能看起来像 演示版

  • 问题内容: 该表用于存储会话(事件): 我们不想在范围之间产生冲突。 假设我们需要在 2010-01-05 至 2010-01-25之间 插入一个新会话。 我们想知道有冲突的会话。 这是我的查询: 结果如下: 有没有更好的方法来做到这一点? 小提琴 问题答案: 我曾经用日历应用程序进行过这样的查询。我想我使用了这样的东西: 更新 这肯定应该工作((ns,ne,es,ee)=(new_start,n

  • 问题内容: 我有一个看起来像这样的数据库表: 写入此日志时,它包含日志记录和unix时间戳。我需要的是获取每周报告,以了解每周有多少日志记录。这是我写的查询: 这给出了这样的结果: 伟大的!但是我想看到的是一个日期范围,如,所以我的结果集如下所示: 有什么办法吗? 问题答案: 使用以获得合适的日期一样,然后用得到你需要的格式。

  • 问题内容: 动态创建日期范围以便与报表配合使用的最佳方法。 因此,如果给定的一天没有活动,我可以避免报表上的空行。 通常是为了避免此问题:在sql结果中(在mysql或perl端)填充空日期的最直接方法是什么? 问题答案: 在MySQL中,没有直接的方法可以做到这一点。最好的选择是用您选择的服务器端语言生成一个daterange数组,然后从数据库中提取数据,并使用date作为键将结果数组与date

  • 问题内容: 我有一张可以容纳一年中所有天/月的表 例如 我有一张表格,显示来自不同数据集的日期范围 例如 我如何比较这两个表以显示该特定月份的数据集中缺少哪些日期 对于上面示例中的数据集所在的示例,EG缺少日期范围01/09/2013-19/09/2013 谢谢你的帮助! 问题答案: 您可以使用CTE并通过以下方式编写查询:

  • 问题内容: 我在MySQL中有一张表,该表显示了我每天记录的小时数。我正在尝试建立一个视图,该视图将允许我按块/天范围快速将数据分组。最简单的情况是每月一次,这并不难。我可以将日期选择为“%y-%m”,然后按该列分组。 前任: 如果我按月分组,那很好。但是我的问题是,我需要从每月的13号到下个月的12号进行分组(例如:7月13日至8月12日,8月13日至9月12日,等等)。 有没有一种简单的方法可