Ето първата част:Припокриващи се автомобили на потребител...
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), за да видите дали можете да намерите различен запис, който се припокрива за времето на текущия запис. Ако намерим такъв, изберете текущия запис, който проверяваме (във всички автомобили).
Следователно припокриването проверката е:
-
allCars
userid
иoverLap
userid
трябва да са еднакви -
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
.