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 iloverLap
userid
deve essere lo stesso -
il
allCars
record dell'auto e laoverlap
record dell'auto deve essere diverso -
il
allCars
intervallo di tempo e iloverLap
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
.