Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie vergleiche ich überlappende Werte innerhalb einer Zeile?

Shahkalpesh beantwortete die Frage mit:

Ich habe einen Kommentar gepostet, dass ich dies für falsch halte, und zwei Gegenbeispiele gegeben:

Als Antwort auf meinen Kommentar bat Shahkalpesh:

Fair genug - ja. Leicht bearbeitet, die Frage lautet:

  • von 7:00 bis 13:00 Uhr oder
  • von 9.00 bis 13.00 Uhr oder
  • von 9.00 bis 17.00 Uhr.

Genug Hintergrund. Wir können das Datum der Termine ignorieren und nur die Zeiten berücksichtigen. Ich gehe davon aus, dass es eine einfache Möglichkeit gibt, die im hh:mm-Format aufgezeichneten Zeiten zu begrenzen. nicht alle DBMS bieten das tatsächlich, aber die Erweiterung zur Handhabung von hh:mm:ss ist trivial.

Appointments

Row     timeStart   timeEnd   Note
  1     07:00       13:00     First valid range
  2     09:00       13:00     Second valid range
  3     09:00       17:00     Third valid range
  4     14:00       17:00     First plausibly valid range
  5     05:00       06:00     First probably invalid range
  6     18:00       22:30     Second probably invalid range

Bei einer Suche nach Terminen, die sich im Bereich von 09:00 bis 13:00 Uhr überschneiden, lautet die (vereinfachte) Abfrage von Shahkalpesh:

SELECT * FROM Appointments
    WHERE (timeStart >= '09:00' OR timeEnd <= '13:00')

Dadurch werden alle sechs Datenzeilen zurückgegeben. Allerdings überschneiden sich nur die Zeilen 1, 2, 3 mit dem Zeitraum 09:00 - 13:00. Wenn die Zeilen 1, 2 und 3 die einzigen gültigen repräsentativen Terminwerte sind, dann erzeugt die Abfrage von Shahkalpesh die richtige Antwort. Wenn jedoch die Zeile 4 (die meiner Meinung nach plausibel gültig ist) zulässig ist, sollte sie nicht zurückgegeben werden. Ebenso sollten die Zeilen 5 und 6 – falls vorhanden – nicht zurückgegeben werden. [Eigentlich, vorausgesetzt timeStart <= timeEnd für alle Zeilen in der Tabelle (und es gibt keine NULL-Werte, die Dinge durcheinander bringen könnten), können wir sehen, dass die Abfrage von Shahkalpesh JEDE Datenzeile für die Abfrage 09:00-13:00 zurückgibt, da entweder die Startzeit von die Zeile ist größer als 09:00 oder die Endzeit ist kleiner als 13:00 oder beides. Dies ist gleichbedeutend mit Schreiben 1 = 1 oder jede andere Tautologie in der WHERE-Klausel. ]

Betrachten wir die Abfrage von ShaneD (vereinfacht):

SELECT * FROM Appointments
    WHERE timeStart <= '13:00' AND timeEnd >= '09:00'

Wir sehen, dass es auch die Zeilen 1, 2 und 3 auswählt, aber die Zeilen 4 (weil timeStart> '13:00'), 5 (weil timeEnd <'09:00') und 6 (weil timeStart> '13:00'). Dieser Ausdruck ist ein archetypisches Beispiel dafür, wie Zeilen ausgewählt werden, die sich „überschneiden“, wobei „meets“ und „met by“ gezählt werden (siehe „Allens Intervallalgebra " zum Beispiel) als überlappend. Das Ändern von '>=' und '<=' ändert den Satz von Intervallen, die als überlappend gezählt werden.