sql >> Base de Datos >  >> RDS >> Mysql

Encuentre superposiciones de rangos de fechas dentro de la misma tabla, para usuarios específicos de MySQL

Aquí está la primera parte:Autos superpuestos por usuario...

SQLFiddle:consulta correlacionada y consulta de combinación

Segunda parte:más de un usuario en un automóvil al mismo tiempo:SQLFiddle:consulta y unión correlacionadas Consulta . Consulta a continuación...

Uso las consultas correlacionadas:

Es probable que necesite índices en ID de usuario y 'automóvil'. Sin embargo, verifique el 'plan de explicación' para ver cómo mysql está accediendo a los datos. E inténtalo :)

Vehículos superpuestos por usuario

La consulta:

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`;      

Los resultados:

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

¿Por qué funciona? o Cómo lo pienso:

Utilizo la consulta correlacionada para no tener duplicados con los que lidiar y probablemente sea la más fácil de entender para mí. Hay otras formas de expresar la consulta. Cada uno tiene ventajas y desventajas. Quiero algo que pueda entender fácilmente.

Requisito:para cada usuario, asegúrese de que no tengan dos o más automóviles al mismo tiempo.

Entonces, para cada registro de usuario (AllCars) revise la tabla completa (overlapCar) para ver si puede encontrar un diferente registro que se superpone a la hora del registro actual. Si encontramos uno, seleccione el registro actual que estamos comprobando (en allCars).

Por lo tanto, la superposición el cheque es:

  • los allCars userid y el overLap userid debe ser el mismo

  • los allCars registro del coche y la overlap registro de coche debe ser diferente

  • los allCars rango de tiempo y el overLap el intervalo de tiempo debe superponerse.

    La verificación del intervalo de tiempo:

    En lugar de verificar los tiempos superpuestos, use pruebas positivas. El enfoque más fácil es verificar que no se superponga y aplicar un NOT a ella.

Un coche con más de un usuario al mismo tiempo...

La consulta:

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`;

 

Los resultados:

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

Editar:

En vista de los comentarios, por @philipxy, sobre los rangos de tiempo que necesitan verificaciones 'mayores o iguales a', actualicé el código aquí. No he cambiado los SQLFiddles .