Zde je první část:Překrývající se auta na uživatele...
SQLFiddle – korelovaný dotaz a dotaz připojení
Druhá část – více než jeden uživatel v jednom autě současně:SQLFiddle – korelovaný dotaz a spojení Dotaz . Dotaz níže...
Používám korelované dotazy:
Pravděpodobně budete potřebovat indexy na userid a 'car'. Nicméně - zkontrolujte prosím 'vysvětlení plánu', abyste viděli, jak mysql přistupuje k datům. A prostě to zkuste :)
Překrývající se vozy na uživatele
Dotaz:
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`;
Výsledky:
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
Proč to funguje? nebo Jak o tom přemýšlím:
Používám korelovaný dotaz, takže nemám duplikáty, které bych řešil, a je pro mě pravděpodobně nejsnáze srozumitelný. Existují i jiné způsoby vyjádření dotazu. Každá má výhody i nevýhody. Chci něco, čemu snadno porozumím.
Požadavek:U každého uživatele se ujistěte, že nemá dvě nebo více aut současně.
Takže pro každý uživatelský záznam (AllCars) zkontrolujte úplnou tabulku (overlapCar), abyste zjistili, zda nenajdete jiné záznam, který se překrývá v době aktuálního záznamu. Pokud nějaký najdeme, vyberte aktuální záznam, který kontrolujeme (v allCars).
Proto překrytí kontrola je:
-
allCars
userid
aoverLap
userid
musí být stejné -
allCars
záznam vozu aoverlap
záznam vozu musí být jiný -
allCars
časový rozsah aoverLap
časový rozsah se musí překrývat.Kontrola časového rozsahu:
Místo kontroly překrývajících se časů použijte pozitivní testy. Nejjednodušší přístup je zkontrolovat, zda se nepřekrývá, a použít
NOT
k tomu.
Jedno auto s více než jedním uživatelem současně...
Dotaz:
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`;
Výsledky:
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
Upravit:
S ohledem na komentáře od @philipxy o časových rozsazích vyžadujících kontroly „větší než nebo rovno“ jsem zde kód aktualizoval. Nezměnil jsem SQLFiddles
.