Mysql
 sql >> Database >  >> RDS >> Mysql

Trova le sovrapposizioni dell'intervallo di date all'interno della stessa tabella, per l'utente specifico MySQL

Ecco la prima parte:Auto sovrapposte per utente...

SQLFiddle - query correlate e join query

Seconda parte - più di un utente in un'auto contemporaneamente:SQLFiddle - query e join correlati Interroga . Domanda sotto...

Uso le query correlate:

Probabilmente avrai bisogno di indici su userid e 'car'. Tuttavia, controlla il "piano esplicativo" per vedere come mysql sta accedendo ai dati. E provalo :)

Auto sovrapposte per utente

La domanda:

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

I risultati:

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

Perché funziona? o Come ci penso:

Uso la query correlata in modo da non avere duplicati da gestire ed è probabilmente la più facile da capire per me. Esistono altri modi per esprimere la query. Ognuno ha vantaggi e svantaggi. Voglio qualcosa che posso capire facilmente.

Requisito:per ogni utente assicurati che non abbia due o più auto contemporaneamente.

Quindi, per ogni record utente (AllCars) controlla la tabella completa (overlapCar) per vedere se riesci a trovare un diverso record che si sovrappone per l'ora del record corrente. Se ne troviamo uno, seleziona il record corrente che stiamo controllando (in allCars).

Pertanto la sovrapposizione il controllo è:

  • il allCars userid e il overLap userid deve essere lo stesso

  • il allCars record dell'auto e la overlap record dell'auto deve essere diverso

  • il allCars intervallo di tempo e il overLap l'intervallo di tempo deve sovrapporsi.

    Il controllo dell'intervallo di tempo:

    Invece di verificare la sovrapposizione dei tempi, utilizzare test positivi. L'approccio più semplice è controllare che non si sovrapponga e applicare un NOT ad esso.

Un'auto con più utenti contemporaneamente...

La domanda:

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

 

I risultati:

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

Modifica:

Alla luce dei commenti, di @philipxy , sugli intervalli di tempo che necessitano di controlli "maggiori o uguali a", ho aggiornato il codice qui. Non ho cambiato SQLFiddles .