Hier ist der erste Teil:Überlappende Autos pro Benutzer...
SQLFiddle - korrelierte Abfrage und Join-Abfrage
Zweiter Teil - mehr als ein Benutzer gleichzeitig in einem Auto:SQLFiddle - korrelierte Abfrage und Verknüpfung Abfrage . Abfrage unten...
Ich verwende die korrelierten Abfragen:
Sie benötigen wahrscheinlich Indizes für Benutzer-ID und „Auto“. Bitte überprüfen Sie jedoch den 'Explain Plan', um zu sehen, wie mysql auf die Daten zugreift. Und probiere es einfach aus :)
Überlappende Autos pro Nutzer
Die Abfrage:
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`;
Die Ergebnisse:
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
Warum es funktioniert? oder wie ich darüber denke:
Ich verwende die korrelierte Abfrage, damit ich nicht mit Duplikaten umgehen muss, und sie ist wahrscheinlich am einfachsten für mich zu verstehen. Es gibt andere Möglichkeiten, die Abfrage auszudrücken. Jeder hat Vor- und Nachteile. Ich möchte etwas, das ich leicht verstehen kann.
Anforderung:Stellen Sie für jeden Benutzer sicher, dass er nicht zwei oder mehr Autos gleichzeitig hat.
Überprüfen Sie also für jeden Benutzerdatensatz (AllCars) die vollständige Tabelle (overlapCar), um zu sehen, ob Sie einen anderen finden können Aufzeichnung, die sich mit der Zeit der aktuellen Aufzeichnung überschneidet. Wenn wir einen finden, wählen Sie den aktuellen Datensatz aus, den wir prüfen (in allCars).
Daher die Überschneidung Prüfung ist:
-
die
allCars
userid
und deroverLap
userid
muss gleich sein -
die
allCars
Fahrzeugrekord und dieoverlap
Autodatensatz muss unterschiedlich sein -
die
allCars
Zeitbereich und deroverLap
Zeitbereich muss sich überschneiden.Zeitbereichsprüfung:
Anstatt nach sich überschneidenden Zeiten zu suchen, verwenden Sie positive Tests. Der einfachste Ansatz besteht darin, zu überprüfen, ob es sich nicht überschneidet, und ein
NOT
anzuwenden dazu.
Ein Auto mit mehr als einem Benutzer gleichzeitig...
Die Abfrage:
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`;
Die Ergebnisse:
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
Bearbeiten:
In Anbetracht der Kommentare von @philipxy über Zeitbereiche, die Prüfungen auf „größer als oder gleich“ erfordern, habe ich den Code hier aktualisiert. Ich habe die SQLFiddles
nicht geändert .