sql >> Database >  >> RDS >> Mysql

Hoe vergelijk ik overlappende waarden binnen een rij?

Shahkalpesh beantwoordde de vraag met:

Ik heb een opmerking geplaatst dat ik dit onjuist vind, waarbij ik een paar tegenvoorbeelden gaf:

In een reactie op mijn opmerking verzocht Shahkalpesh:

Eerlijk genoeg - ja. Iets aangepast, de vraag zegt:

  • van 7.00 tot 13.00 uur, of
  • van 9.00 tot 13.00 uur, of
  • van 9.00 tot 17.00 uur.

Genoeg achtergrond. We kunnen de datum van de afspraken negeren, en alleen maar aan de tijden denken. Ik ga ervan uit dat er een gemakkelijke manier is om de opgenomen tijden te beperken tot hh:mm-formaat; niet alle DBMS bieden dat echt, maar de extensie om hh:mm:ss te verwerken is triviaal.

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

Gegeven een zoekopdracht naar afspraken die het bereik 09:00 - 13:00 overlappen, wordt de (vereenvoudigde) vraag van Shahkalpesh:

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

Hiermee worden alle zes gegevensrijen geretourneerd. Alleen rijen 1, 2, 3 overlappen echter de tijdsperiode 09:00 - 13:00. Als rijen 1, 2 en 3 de enige geldige representatieve afspraakwaarden zijn, levert de zoekopdracht van Shahkalpesh het juiste antwoord op. Als rij 4 (waarvan ik denk dat die aannemelijk is) is toegestaan, mag deze echter niet worden geretourneerd. Evenzo mogen rijen 5 en 6 - indien aanwezig - niet worden geretourneerd. [Eigenlijk, ervan uitgaande dat timeStart <= timeEnd voor alle rijen in de tabel (en er zijn geen NULL-waarden om dingen te verknoeien), kunnen we zien dat de query van Shahkalpesh ELKE rij met gegevens voor de query van 09:00-13:00 retourneert, omdat ofwel de starttijd van de rij is groter dan 09:00 of de eindtijd is minder dan 13:00 of beide. Dit komt neer op schrijven 1 = 1 of een andere tautologie in de WHERE-clausule. ]

Als we de vraag van ShaneD (vereenvoudigd) beschouwen:

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

we zien dat het ook rijen 1, 2 en 3 selecteert, maar het verwerpt rijen 4 (omdat timeStart> '13:00'), 5 (omdat timeEnd <'09:00') en 6 (omdat timeStart> '13:00'). Deze uitdrukking is een archetypisch voorbeeld van het selecteren van rijen die 'overlappen', 'meets' en 'met by' tellen (zie "Allen's intervalalgebra ", bijvoorbeeld) als overlappend. Door '>=' en '<=' te wijzigen, wordt de reeks intervallen die als overlappend worden geteld, gewijzigd.



  1. Een IN-clausule gebruiken met MySQL met opgegeven waarden

  2. Transactie-isolatie in PostgreSQL

  3. Een relationeel databaseschema leegmaken

  4. invoegen in database vanuit dubbel tekstveld indien niet leeg php sql