sql >> Database >  >> RDS >> Mysql

Vind overlap van datumbereiken binnen dezelfde tabel, voor specifieke gebruiker MySQL

Hier is het eerste deel:Overlappende auto's per gebruiker...

SQLFiddle - gecorreleerde Query en Join Query

Tweede deel - meer dan één gebruiker tegelijk in één auto:SQLFiddle - gecorreleerde Query en Join Zoekopdracht . Vraag hieronder...

Ik gebruik de gecorreleerde zoekopdrachten:

U zult waarschijnlijk indexen nodig hebben op userid en 'car'. Controleer echter het 'plan uitleggen' om te zien hoe mysql toegang heeft tot de gegevens. En probeer het gewoon :)

Overlappende auto's per gebruiker

De vraag:

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

De resultaten:

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

Waarom werkt het? of Hoe ik erover denk:

Ik gebruik de gecorreleerde query, zodat ik geen duplicaten heb om mee om te gaan en het is waarschijnlijk het gemakkelijkst te begrijpen voor mij. Er zijn andere manieren om de vraag uit te drukken. Elk heeft voor- en nadelen. Ik wil iets dat ik gemakkelijk kan begrijpen.

Vereiste:Zorg ervoor dat elke gebruiker niet twee of meer auto's tegelijk heeft.

Controleer dus voor elk gebruikersrecord (AllCars) de volledige tabel (overlapCar) om te zien of u een andere kunt vinden record dat overlapt voor de tijd van het huidige record. Als we er een vinden, selecteer dan het huidige record dat we controleren (in allCars).

Daarom is de overlap controle is:

  • de allCars userid en de overLap userid moet hetzelfde zijn

  • de allCars autorecord en de overLap autorecord moet anders zijn

  • de allCars tijdbereik en de overLap tijdbereik moet overlappen.

    De tijdbereikcontrole:

    Gebruik positieve tests in plaats van te controleren op overlappende tijden. De eenvoudigste benadering is om te controleren of het niet overlapt, en een NOT . toe te passen ernaartoe.

Eén auto met meer dan één gebruiker tegelijk...

De vraag:

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

 

De resultaten:

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

Bewerken:

Met het oog op de opmerkingen van @philipxy over tijdbereiken waarvoor controles 'groter dan of gelijk aan' nodig zijn, heb ik de code hier bijgewerkt. Ik heb de SQLFiddles niet veranderd .



  1. NUMTOYMINTERVAL() Functie in Oracle

  2. Incrementele statistieken worden NIET gebruikt door de Query Optimizer

  3. Alleen-lezen gebruiker maken in PostgreSQL

  4. Hoe Raw SQL uit te voeren in SQLAlchemy