So wählen Sie mit joins und nur die Rückgabe von Zeilen aus einer Tabelle?

Ich habe eine Datenbank die wie folgt aussieht: https://i.imgur.com/dwaqUF2.png

Ich möchten, wählen Sie alle Zimmer, die Sie nicht haben eine Reservierung für einen bestimmten Zeitraum.

Hier ist, was ich versucht habe:

SELECT idRoom, type, beds FROM Room r
INNER JOIN Reservation_has_Room has on r.idRoom = has.Room_idRoom
INNER JOIN Rezervation re on has.Reservation_has_Room = re.idReservation
 WHERE (re.checkIn<'2019-06-04'
 AND re.checkOut<'2019-06-01') 
 or
(re.checkIn>'2019-06-04'
 AND re.CheckOut>'2019-06-01');

Aber dieses Skript gibt einen Raum jedes mal, wenn es feststellt, eine Reservierung ist nicht überlappend das Datum.

2 Antworten

  • Tim Biegeleisen
    4. Mai 2019

    Dies ist der überlappende Bereich Probleme, und Ihr WHERE Klausel sollte:

    WHERE
        re.checkIn <= '2019-06-04' AND
        re.checkOut >= '2019-06-01'
    

    Ihre vollständige Abfrage:

    SELECT
        idRoom,
        type,
        beds
    FROM Room r
    INNER JOIN Reservation_has_Room has
        ON r.idRoom = has.Room_idRoom
    INNER JOIN Rezervation re
        ON has.Reservation_has_Room = re.idReservation
    WHERE
        re.checkIn <= '2019-06-04' AND
        re.checkOut >= '2019-06-01';
    
  • AlexYes
    4. Mai 2019

    Ja, es ist so, da machst du einen inner join und filter die Reservierungen. Was Sie brauchen, ist Zimmer left join Buchungen auf den Zeitraum, Bedingungen und dann filter-Einheiten, die nicht irgendwelche Vorbehalte beigetreten:

    SELECT idRoom, type, beds 
    FROM Room r
    LEFT JOIN Reservation_has_Room has 
    ON r.idRoom = has.Room_idRoom
    LEFT JOIN Rezervation re 
    ON has.Reservation_has_Room = re.idReservation
    AND (
        re.checkIn <= '2019-06-01' AND re.checkOut >= '2019-06-04' -- (1)
        or re.checkIn between '2019-06-01' and '2019-06-04' -- (2)
        or re.checkOut between '2019-06-01' and '2019-06-04' -- (3)
    )
    WHERE re.checkIn is null -- filter out units that don't have matching reservations
    

    die join-Bedingung der obigen 3 Fälle:

    1) vollständig überlappenden Reservierungen 2) Vorbehalte, die irgendwo beginnen in der Mitte des Zeitraums und Ende einige Zeit nach 3) Reservierungen, die beginnen, einige Zeit vor und am Ende irgendwo in der Mitte der Periode

    Der Zustand von Tim vorgeschlagen, könnte auch funktionieren. Aber der wichtigste Punkt ist die Umstellung auf LEFT JOIN mit range-filtern in der join-Bedingung und haben WHERE re.checkIn is null

    Um Ihre Lösung mehr Dynamik, die Sie verwenden würden, Unterabfragen, um die Zeit angeben, Grenzen, nur einmal, und wiederverwenden Sie diese Werte in den filter:

    WITH
     start_date as (select '2019-06-01'::date)
    ,end_date as (select '2019-06-04'::date)
    

    und dies als eine join-Bedingung:

    (
        re.checkIn <= (select * from start_date) AND re.checkOut >= (select * from end_date) -- (1)
        or re.checkIn between (select * from start_date) and (select * from end_date) -- (2)
        or re.checkOut between (select * from start_date) and (select * from end_date) -- (3)
    )