Ето първата част:Припокриващи се автомобили на потребител...
SQLPiddle – корелирана заявка и заявка за присъединяване
Втора част - повече от един потребител в една кола едновременно:SQLPiddle - свързано запитване и присъединяване Запитване . Запитване по-долу...
Използвам свързаните заявки:
Вероятно ще ви трябват индекси на userid и 'car'. Въпреки това - моля, проверете "плана за обяснение", за да видите как mysql осъществява достъп до данните. И просто опитайте :)
Припокриващи се автомобили на потребител
Запитването:
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`;
Резултатите:
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
Защо работи? или Как мисля за това:
Използвам корелираната заявка, така че нямам дубликати, с които да се справя и вероятно е най-лесният за разбиране за мен. Има и други начини за изразяване на заявката. Всеки има предимства и недостатъци. Искам нещо, което лесно мога да разбера.
Изискване:За всеки потребител се уверете, че няма две или повече коли едновременно.
Така че, за всеки потребителски запис (AllCars) проверете пълната таблица (overlapCar), за да видите дали можете да намерите различен запис, който се припокрива за времето на текущия запис. Ако намерим такъв, изберете текущия запис, който проверяваме (във всички автомобили).
Следователно припокриването проверката е:
-
allCarsuseridиoverLapuseridтрябва да са еднакви -
allCarsзапис на автомобила иoverlapзаписът на автомобила трябва да е различен -
allCarsвремеви диапазон иoverLapвремевият диапазон трябва да се припокрива.Проверка на времевия диапазон:
Вместо да проверявате за припокриващи се времена, използвайте положителни тестове. Най-лесният подход е да проверите дали не се припокрива и да приложите
NOTкъм него.
Една кола с повече от един потребител едновременно...
Запитването:
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`;
Резултатите:
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
Редактиране:
С оглед на коментарите от @philipxy относно времеви диапазони, изискващи проверки „по-голямо от или равно на“, актуализирах кода тук. Не съм променил SQLFiddles .