SQL Abfrage begindate und enddate - Tag der im Zeitraum liegt ausgeben. Zimmerbuchung.

maximiliansport

Benutzer
Beiträge
7
Hallo liebes Forum,
ich habe gerade einen Knoten im Kopf, vielleicht könnt ihr mir helfen:
Ich habe eine Gästetabelle, die das Beginn- und Enddatum eines Aufenthalts erhält. Quasi wie eine Zimmerbuchung für Übernachtungen.
Ich möchte herausfinden, welche Gäste in der Woche an welchen Tagen gastieren.
Bedeutet - so denk eich - ich führe für jeden Tag (Mo-So) eine SQL-Abfrage durch, welche mir die Gäste auflistet, die an jenem Tag (Montag z.B. 27.06.2022) ein Zimmer belegen.

Wie bekomm ich das denn hin?

Weil mit:
SELECT * FROM `guests` WHERE `begindate` >= '2022-06-27' and `begindate`<='2022-07-03'
Und mit Between '2022-06-27' and '2022-07-03' habe ich ja auch nur den Wochenzeitraum. Aber daraus möchte ich ja jeweils die einzelnen Tage aufgelistet haben.

Ich weiß, dass es gehen muss aber ich komme gerade überhaupt nicht weiter.

Könnt ihr mir helfen?
Herzlichen Dank :)

Meine Beispielstabelle für diese Woche sieht folgend aus:

Idfirstnamelastnamebegindateendate
1OttoMustermann2022-06-272022-07-02
2ChristineLeckerundnächstewoche2022-07-012022-07-11
3FrederikeMustermann2022-07-022022-07-02
4PaulAndergrenze2022-07-032022-07-03
5FredNurnächstewoche2022-07-042022-07-09
6AnnaHubervorherigeWoche2022-06-212022-06-22
7PetraSchönvorherigeundaktuelleWoche2022-06-252022-06-28
 
Werbung:
Ich habe das mal mit PostgreSQL nachgebildet, für den Belegungszeitraum hier mit DATERANGE. Da frederike und paul nicht über Nacht bleiben, ist da auch kein Eintrag:

Code:
postgres=# select * from maximiliansport;
 id | firstname |         von_bis        
----+-----------+-------------------------
  1 | otto      | [2022-06-27,2022-07-02)
  2 | christine | [2022-07-01,2022-07-11)
  3 | frederike | empty
  4 | paul      | empty
  5 | fred      | [2022-07-04,2022-07-09)
  6 | anna      | [2022-06-21,2022-06-22)
  7 | petra     | [2022-06-25,2022-06-28)
(7 rows)

Wer ist in der Woche vom 27.6. bis 3.7. da?

Code:
postgres=# with tage as (select * from generate_Series('2022-06-27'::date, '2022-07-03'::date, '1day'::interval) as tag) select tage.tag, string_agg(m.firstname,', ') from tage left join maximiliansport m on m.von_bis @> tage.tag::date group by tage.tag;
          tag           |   string_agg   
------------------------+-----------------
 2022-06-27 00:00:00+00 | otto, petra
 2022-06-28 00:00:00+00 | otto
 2022-06-29 00:00:00+00 | otto
 2022-06-30 00:00:00+00 | otto
 2022-07-01 00:00:00+00 | otto, christine
 2022-07-02 00:00:00+00 | christine
 2022-07-03 00:00:00+00 | christine
(7 rows)

postgres=#

Ist das das Ergebniss, was Du suchst?
 
Hallo akretschmer,
Danke für deine Antwort! :)
Fast.
Fast schon zu geil. :)

Zum Verständnis für mich noch einfacher (hoffentlich):
Wenn ich jetzt nur den Montag, 27.06.2022 haben möchte.
Also nur die, die am 27.06. ein Zimmer haben.
Es zählt auch tagsüber. Sie können übernacht bleiben, müssen aber nicht. Sie zählen dennoch rein.
 
Code:
postgres=# with tage as (select * from generate_Series('2022-06-27'::date, '2022-06-27'::date, '1day'::interval) as tag) select tage.tag, string_agg(m.firstname,', ') from tage left join maximiliansport m on m.von_bis @> tage.tag::date group by tage.tag;
          tag           | string_agg  
------------------------+-------------
 2022-06-27 00:00:00+00 | otto, petra
(1 row)

postgres=#

Wenn jemand nur am Tage das Zimmer braucht, müßte man es dennoch bis zum nächsten Tag buchen, damit es als belegt gilt. Der Abreisetag ist sowieso immer exclusive, daher auch die ) Klammer am Abreisetag und die [ am Anreisetag.
 
wenn es nur für einen Tag ist, geht das auch einfacher, dann kann man sich ja die generierung der 7 Tage sparen:

Code:
postgres=# select string_agg(m.firstname,', ') from maximiliansport m where m.von_bis @> '2022-06-27'::date;
 string_agg  
-------------
 otto, petra
(1 row)
 
Du kannst auch einen Constraint definieren, daß einzelne Zimmer nicht mehrfach belegt werden, das ganze geht auch via Index sehr schnell.

nur halt Pech für Dich: MySQL kann das alles nicht.
 
Wenn das MySQl nicht kann, dann bringt mir das natürlich nicht so viel ;-)
Am Ende wirds noch in PHP verwurstet.

Kann ich das in mysql sicher absolut nicht lösen?
 
Bin nicht sicher was du jetzt als Ergebnis wirklich willst aber um das Ergebnis aus #2 zu bekommen geht das auch einfach in mySQL8

Code:
SELECT date, GROUP_CONCAT(dates.firstname)
FROM (WITH RECURSIVE nrows(date) AS
(
SELECT '2022-06-27'
  UNION ALL
    SELECT DATE_ADD(date,INTERVAL 1 day) FROM nrows WHERE  date<='2022-07-03'
)
SELECT date
FROM nrows) i
LEFT JOIN dates ON dates.begindate <= date and dates.enddate >= date
GROUP BY date

 
Hallo Thallius!
Doch hast du verstanden.
Danke! Und Danke für den Fiddle Link! - Das ist ja genail!
Den Knoten hab ich jetzt direkt verstanden, das war im Prinzip das hier:

SQL:
SELECT * FROM guests WHERE begindate <= '2022-06-27' AND enddate >= '2022-06-27';
Mein Fehler: endate nicht mitreinzunehmen und größer Zeichen.

Aber diese deine Lösung über mySQL ;-) ist besser, weil nur eine Abfrage.
Gedanklich war ich dabei, für jeden Tag eine Abfrage durchzuführen, was natürlich nicht toll wäre.

Cool! Herzlichen Dank.
Danke an alle :) Auch an den Hinweis auf postgresql :)
 
Code:
SELECT * FROM guests WHERE begindate <= '2022-06-27' AND enddate >= '2022-06-27';
kannst du noch vereinfachen mit
Code:
SELECT * FROM guests WHERE '2022-06-27' BETWEEN begindate AND enddate;
 
Wenn du das **GROUP_CONCAT** noch um **ORDER BY** erweiterst bekommst du die Namen auch immer alphabetisch angezeigt.

**GROUP_CONCAT(dates.firstname ORDER BY dates.firstname)**
 
Kann ich das Ergebnis eines GROUP_CONCAT Zeilenweise auslesen? wie mit foreach-Schleifen?
Nein oder?
Also aus obrig 1. Zeile (2022-06-27) die z.B. Namen für jenen Montag rausziehen.

Später dann die einzelnen Namen separieren - Trennsymbol für den nächsten Namen wäre dann das Komma. (vermutlich in PHP mit so was wie $variableAusgabe = explode(",", $HierIstMeineGesamteZeile))

Hintergrund:
Ich habe einen PHP Wochenkalender. Montag, 27.06.2022 bis Sonntag 03.07.2022. Zum Durchblättern +/- Woche.
Und halt weitere Zeilen unter den Wochentagen, wo die Gäste reinsollen.
Ich dachte mir, ich fülle in PHP ein Array mit den Namen des jeweiligen Tages aus der SQL-Abfrage.
Und gebe das dann in der Tabelle meines Kalenders aus.
 
Werbung:
Du kannst auch auf die Gruppierung verzichten, dann bekommst gleich mehrere Zeilen:

Code:
postgres=# select string_agg(m.firstname,', ') from maximiliansport m where m.von_bis @> '2022-06-27'::date;
 string_agg  
-------------
 otto, petra
(1 row)

postgres=# select m.firstname from maximiliansport m where m.von_bis @> '2022-06-27'::date;
 firstname 
-----------
 otto
 petra
(2 rows)
 
Zurück
Oben