2009-04-23 3 views
1

In my question about searching for date ranges habe ich versucht, das Problem zu vereinfachen und versehentlich ein anderes und einfacheres Problem gestellt.Suche nach freien Steckplätzen in einem Buchungssystem

Anstatt diese Frage mit einer Bearbeitung zu komplizieren, werde ich das Problem stellen, das ich eigentlich beabsichtigte.

Ich habe zwei Tabellen Eigentum und Buchung. Buchungen haben einen Fremdschlüssel zu Eigenschaften sowie Start- und Enddatum.

Der Benutzer sucht nach freien Steckplätzen und liefert eine gewünschte Dauer in Tagen. Sie liefern auch eine Reihe von Starttermine, an denen sie interessiert sind. Daher wird eine Suche nach folgenden Kriterien durchgeführt: "Finden Sie alle Eigenschaften Ich möchte einen 3-Tage-Slot, der jederzeit im Mai beginnt."

Jetzt kann ich dies tun, indem: 1. Rennen 31 Abfragen für jeden potentiellen Starttag 2. alle Buchungen Mai zu finden, kondensieren sie in einer Reihe von 31 booleans Tage und Schleife durch für Schlitze Suche darstellt.

Ich nehme an (2) ist in den meisten Fällen effizienter. Gibt es bessere Algorithmen? Gibt es eine reine SQL-Lösung?

Ich werde Django verwenden und mein Dataset ist klein, also werde ich wahrscheinlich mit einem 'dummen' Approch in Ordnung sein, aber ich bin gespannt, wie der beste Algorithmus aussieht.

Antwort

4

für Ihre Anwendung wahrscheinlich übertrieben - aber:

Eine relativ einfache Möglichkeit, Ihre Suche auf Kosten der Verbesserung der Herstellung der ‚schreiben‘ Prozess komplizierter, wäre die Buchung Tabelle ändern es eine ‚Verfügbarkeit zu machen ' Tabelle.

Fügen Sie eine boolesche Spalte hinzu, um anzuzeigen, ob der Slot frei oder gebucht ist (oder besser noch die ID des Kunden, der ihn gebucht hat, und 0, wenn der Slot frei ist).

Beginnen Sie mit einem freien Platz, 1. Januar 2009 -> 31. Dezember 20 ??

Wenn Sie eine Buchung erhalten teilen Sie den freien Platz in 3 (zwei Einsätze und ein Update), den gebuchten Platz und die zwei verfügbaren Plätze.

Halten Sie das tun und wie der Zeitrahmen stärker fragmentiert bekommt, wird die Buchung eines der folgenden bestehen:

  • einen ganzen ‚freien Steckplatz‘ zuordnen zu jemand (ein Update)
  • Splitting ein "verfügbarer Slot" in zwei (ein Update und ein Insert)
  • Einen Slot in 3 aufteilen (wie oben), wenn jemand den mittleren Abschnitt aus einem verfügbaren Slot bucht.

Das ist nicht unglaublich kompliziert zu verwalten und der Suchprozess wird eine einfache Abfrage: keine Schlitze in dem gewünschten Zeitrahmen zu finden, die zur Verfügung stehen (gebucht = false oder customerid = 0, je nachdem, wie Sie mit ihm zu gehen), wo enddate - Startdatum> = die Anzahl der Tage, die Sie möchten.

Es verdoppelt die Größe der Buchungs/Verfügbarkeitstabelle und macht Buchungen weniger einfach, aber der Kompromiss ist, dass der Suchprozess so einfach wie möglich ist.

+0

Sehr klug Ansatz, aber ich brauche die Buchungsdaten für zu viele andere Zwecke. Ich könnte eine Verfügbarkeitstabelle für jede Eigenschaft zusätzlich zu meinem aktuellen Buchungsschema haben. In diesem Sinne denormalisiert meine Daten, um eine Art der Suche zu erleichtern, aber in diesem Fall kann als eine vorzeitige Optimierung zählen. –

+0

Ihre ursprünglichen Buchungsdaten sind immer noch da - sie haben nur eine extra Spalte mit entweder 'booked' boolean oder customerid. Wenn Sie die Verfügbarkeitstabelle mit where booked = true oder customerid> 0 durchsuchen, haben Sie den gleichen Datensatz wie in Ihrer Originaltabelle. Deshalb verdoppelt es die Größe des Tisches und enthält sowohl gebuchte als auch verfügbare Slots. –

+0

+1 Wahrscheinlich nicht die Lösung, die das OP sucht, aber sehr ordentlich. –

4

Tabelle Definitionen hätten geholfen, aber hier geht.Dies sollte für MS SQL Server funktionieren, aber es sollte eine triviale Aufgabe sein, sie in MySQL zu konvertieren, sobald Sie die dahinter stehende Idee verstanden haben.

Die Kalendertabelle ist nur eine Standard-Dienstprogrammtabelle mit allen Daten, die in Ihrer Datenbank nützlich sind. Wenn Sie noch keins haben, schlage ich vor, dass Sie eins erstellen und es ausfüllen.

CREATE TABLE Calendar 
(
    date  DATETIME  NOT NULL, 
    is_holiday BIT   NOT NULL, 
    -- any other columns that might be relevant for your business 
    CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (date) 
) 

Sie müssten dann die Tabelle mit Daten füllen, die für Ihr Unternehmen von Bedeutung sein könnten. Selbst wenn Sie 100 Jahre zurückgehen und 100 Jahre vorziehen, sind das immer noch weniger als 75.000 Zeilen in der Tabelle und es ist auf das Datum geclustert, also sollte es schnell und einfach zu arbeiten sein. Es macht viele datenbasierte Abfragen viel einfacher.

SELECT 
    P.property_id, 
    C.date 
FROM 
    Calendar C 
JOIN Properties P ON 1=1 
WHERE 
    C.date BETWEEN @search_start_date AND @search_end_date AND 
    NOT EXISTS 
    (
      SELECT 
       * 
      FROM 
       Bookings B 
      WHERE 
       B.property_id = P.property_id AND 
       B.start_date <= DATEADD(dy, @slot_length, C.date) AND -- You would use MySQLs date function 
       B.end_date >= C.date 
    ) 

Oder alternativ:

SELECT 
    P.property_id, 
    C.date 
FROM 
    Calendar C 
JOIN Properties P ON 1=1 
LEFT OUTER JOIN Bookings B ON 
       B.property_id = P.property_id AND 
       B.start_date <= DATEADD(dy, @slot_length, C.date) AND -- You would use MySQLs date function 
       B.end_date >= C.date 
WHERE 
    C.date BETWEEN @search_start_date AND @search_end_date AND 
    B.booking_id IS NULL 
+0

Ich bin nicht genau klar, was die Calendar-Tabelle hier enthält? –

+0

Es ist nur eine Tabelle mit Daten. Es ist dort, so dass Sie Daten in einer Set-basierten Weise behandeln können. Ich füge ein Beispiel DDL für die Antwort hinzu. –

+0

Ich habe ein schreckliches Gefühl Ich bin einfach nicht schlau genug, um diese Antwort zu verstehen! Was macht die 'JOIN Properties P ON 1 = 1' Zeile? –