sql >> Databasteknik >  >> RDS >> Mysql

Hitta datumintervallsöverlappningar inom samma tabell, för specifika användare MySQL

Här är den första delen:Överlappande bilar per användare...

SQLFiddle - korrelerad fråga och gå med i fråga

Andra delen - mer än en användare i en bil samtidigt:SQLFiddle - korrelerad Fråga och gå med Fråga . Fråga nedan...

Jag använder de korrelerade frågorna:

Du kommer sannolikt att behöva index på användar-id och "bil". Men - vänligen kontrollera "förklara planen" för att se hur mysql kommer åt data. Och prova bara :)

Överlappande bilar per användare

Frågan:

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

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

Varför fungerar det? eller hur jag tänker kring det:

Jag använder den korrelerade frågan så jag har inga dubbletter att hantera och det är förmodligen det lättaste att förstå för mig. Det finns andra sätt att uttrycka frågan. Var och en har fördelar och nackdelar. Jag vill ha något som jag lätt kan förstå.

Krav:Se till att varje användare inte har två eller flera bilar samtidigt.

Så, för varje användarpost (AllCars) kontrollera hela tabellen (overlapCar) för att se om du kan hitta en annan post som överlappar för tiden för den aktuella posten. Om vi ​​hittar en så välj den aktuella posten som vi kontrollerar (i allCars).

Därför överlappningen kryssrutan är:

  • allCars userid och overLap userid måste vara samma

  • allCars bilrekord och overlap bilrekord måste vara annorlunda

  • allCars tidsintervall och overLap tidsintervallet måste överlappa.

    Tidsintervallskontrollen:

    Använd positiva tester istället för att kontrollera för överlappande tider. Det enklaste tillvägagångssättet är att kontrollera att det inte överlappar och tillämpa en NOT till det.

En bil med fler än en användare samtidigt...

Frågan:

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

 

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

Redigera:

Med tanke på kommentarerna från @philipxy , om tidsintervall som kräver "större än eller lika med" kontroller har jag uppdaterat koden här. Jag har inte ändrat SQLFiddles .



  1. MySQL lagrade procedurer

  2. SSL för PostgreSQL-anslutningsnoder

  3. MySQL FULL JOIN fungerar inte men HÖGER och VÄNSTER går med fungerar

  4. Datetime NU PHP mysql (+ PDO-variant)