sql >> Databasteknik >  >> RDS >> Mysql

Hur jämför jag överlappande värden inom en rad?

Shahkalpesh svarade på frågan med:

Jag postade en kommentar om att jag anser att detta är fel, med ett par motexempel:

I ett svar på min kommentar bad Shahkalpesh:

Fair enough - ja. Något redigerad lyder frågan:

  • från 07.00 till 13.00, eller
  • från 9.00 till 13.00, eller
  • från 9.00 till 17.00.

Tillräckligt med bakgrund. Vi kan strunta i datumet för mötena och bara överväga tiderna. Jag antar att det finns ett enkelt sätt att begränsa de tider som spelas in till formatet hh:mm; inte alla DBMS ger faktiskt det, men tillägget för att hantera hh:mm:ss är trivialt.

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

Med tanke på en sökning efter möten som överlappar intervallet 09:00 - 13:00, blir Shahkalpeshs (förenklade) fråga:

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

Detta kommer att returnera alla sex rader med data. Det är dock endast raderna 1, 2, 3 som överlappar tidsperioden 09:00 - 13:00. Om raderna 1, 2 och 3 är de enda giltiga representativa mötesvärdena, ger Shahkalpeshs fråga det korrekta svaret. Men om rad 4 (som jag tror är rimligt giltig) tillåts, så ska den inte returneras. På samma sätt ska raderna 5 och 6 - om de finns - inte returneras. [Faktiskt, förutsatt timeStart <= timeEnd för alla rader i tabellen (och det finns inga NULL-värden för att förstöra), kan vi se att Shahkalpeshs fråga kommer att returnera ALLA rader med data för 09:00-13:00-frågan eftersom antingen starttiden för raden är större 09:00 eller sluttiden är mindre än 13:00 eller båda. Detta är liktydigt med att skriva 1 = 1 eller någon annan tautologi i WHERE-klausulen. ]

Om vi ​​betraktar ShaneDs fråga (som förenklat):

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

vi ser att den också väljer raderna 1, 2 och 3, men den avvisar raderna 4 (eftersom timeStart> '13:00'), 5 (eftersom timeEnd <'09:00') och 6 (eftersom timeStart> '13:00'). Det här uttrycket är ett arketypiskt exempel på hur man väljer rader som "överlappar", räknar "träffas" och "uppfylls av" (se "Allens intervallalgebra ", till exempel) som överlappande. Om du ändrar '>=' och '<=' ändras uppsättningen av intervaller som räknas som överlappande.



  1. Upptäck om ett datum är i sommartid i MySql

  2. MySQL ignorerar NOT NULL-begränsningen

  3. PostgreSQL procedurspråk C hittades inte

  4. VÄLJ WHERE IN med GROUP_CONCAT som indata