c21: PHP-Kalender: MySQL-Abfrage mit GROUP_CONCAT und UNION

Hallo,

ich möchte eine PHP-Kalender mit Termindaten aus einer MySQL-Datenbank (MySQL 5) befüllen.

Wenn eine Termin noch frei ist (ubf_status = 'N'), soll es einen Link zum Buchungsformular geben.
Wenn eine Termin bereits gebucht ist (ubf_status = 'Y'), soll 'gebucht' hinter der Uhrzeit stehen.
Diese Formatierungen füge ich bereits in der SQL-Abfrage ein (GROUP_CONCAT), da die Einträge pro Kalendertag über
   setCalendarText( &$days, ...)
festgelegt werden.

Wenn es mehrere Termine pro Tag gibt, hab ich jedoch eine Problem.

Beispiel:
2013-07-17 09:00 gebucht
2013-07-17 15:00 gebucht

2013-07-26 10:00 gebucht
2013-07-26 15:00 frei

2013-07-31 10:00 frei
2013-07-31 12:00 frei

Haben beide Termine den selben Status (2013-07-17 und 2013-07-31), passt die Ausgabe.
Sind sie jedoch unterschiedlich (2013-07-26), wird nur ein Eintrag ausgegeben (da sie nicht im selben array stehen).

Wie kann ich meine SQL-Abfrage (eigentlich 2 Abfragen - je nach Termin-Status - mit UNION verknüpft), sodass alle Termine eines Tages im selben array landen, unabhängig vom Termin-Status.
Kann man da nochmals eine GROUP_CONCAT über beide Abfragen machen?

Im Screenshot sieht man die Kalenderbefüllung und die Ausgabe der array-Daten.

Und hier der Quellcode:

-- snip --

// Abfrage  
$anfrage_ubf="( SELECT  
ubf_id,  
ubf_termin_datum,  
ubf_termin_uhrzeit,  
substring(ubf_termin_datum, 1, 4) as ubf_termin_datum_jahr,  
substring(ubf_termin_datum, 6, 2) as ubf_termin_datum_monat,  
substring(ubf_termin_datum, 9, 2) as ubf_termin_datum_tag,  
ubf_status,  
GROUP_CONCAT( '<a href=\"fuehrungen-termin-buchen.php?ubf_id=',ubf_id,'\">',substring(ubf_termin_uhrzeit, 1, 5),' Uhr</a>' ORDER BY ubf_termin_datum ASC, ubf_termin_uhrzeit ASC SEPARATOR '<br />') AS Termin  
FROM ubf  
WHERE ubf_termin_datum >= '$heute'  
AND ubf_typ = 'F'  
AND ubf_status = 'N'  
GROUP BY ubf_termin_datum )  
  
UNION ALL  
  
( SELECT  
ubf_id,  
ubf_termin_datum,  
ubf_termin_uhrzeit,  
substring(ubf_termin_datum, 1, 4) as ubf_termin_datum_jahr,  
substring(ubf_termin_datum, 6, 2) as ubf_termin_datum_monat,  
substring(ubf_termin_datum, 9, 2) as ubf_termin_datum_tag,  
ubf_status,  
GROUP_CONCAT( '<i>',substring(ubf_termin_uhrzeit, 1, 5),' Uhr gebucht</i>' ORDER BY ubf_termin_datum ASC, ubf_termin_uhrzeit ASC SEPARATOR '<br />') AS Termin  
FROM ubf  
WHERE ubf_termin_datum >= '$heute'  
AND ubf_typ = 'F'  
AND ubf_status = 'Y'  
GROUP BY ubf_termin_datum )  
  
ORDER BY ubf_termin_datum ASC, ubf_termin_uhrzeit ASC";  
$ergebnis_ubf = @mysql_query($anfrage_ubf)  
or die("<div class=\"error\">Fehler bei der Datenbankabfrage!</div>");  
  
$anzahl_ubf = @mysql_num_rows($ergebnis_ubf);  
  
$list = array();  
while ($row = mysql_fetch_assoc($ergebnis_ubf)) {  
   $list[] = $row;  
}  
  
foreach ($list as $i => $record) {  
// zur Kontrolle: Auflistung der Daten des arrays  
   echo $i, ". ", $record['ubf_termin_datum_jahr'], "-", $record['ubf_termin_datum_monat'], "-", $record['ubf_termin_datum_tag'], " - ", $record['Termin'], "<br />\n";  
// befuellt den jeweiligen Kalendertag  
   setCalendarText( &$days, $record['ubf_termin_datum_monat'], $record['ubf_termin_datum_tag'], $record['ubf_termin_datum_jahr'], "".$record[Termin]."" );  
}

-- snap --

Danke im Voraus.
Christian.

  1. Tach!

    Diese Formatierungen füge ich bereits in der SQL-Abfrage ein (GROUP_CONCAT),

    Welchen Zweck soll die Gruppierung erfüllen? Warum fragst du nciht einfach nur die Daten ab und formatierst sie im abfragenden Programm?

    substring(ubf_termin_datum, 1, 4) as ubf_termin_datum_jahr,
    substring(ubf_termin_datum, 6, 2) as ubf_termin_datum_monat,
    substring(ubf_termin_datum, 9, 2) as ubf_termin_datum_tag,

    Warum gehst du hier mit Stringfunktionen auf ein Datum los, wo es doch für richtige Datums-Felder spezialisierte Funktionen gibt?

    Kann man da nochmals eine GROUP_CONCAT über beide Abfragen machen?

    Das kann ich jetzt nicht mit Bestimmtheit sagen, aber wenn, dann muss die unionisierte Abfrage als Subselect in einer FROM-Klausel landen, woraufhin du dann wieder GROUP BY etc. anwenden kannst. Ob MySQL sowas zulässt, musst du mal dem Handbuch entnehmen oder probieren.

    Allgemein scheint mir das aber nicht der richtige Weg zu sein. Du hast es jetzt schon komplizierter als nötig (gemäß meinem Bauchgefühl beim groben Überfliegen des Problems). Eine Gruppierung ohne abenteuerliche GROUP_CONCATs bekommt man auch im abfragenden Programm hin. Recherche-Stichwort: Gruppenwechsel.

    dedlfix.

    1. Tach!

      Hallo,

      und danke für die Tipps!

      Diese Formatierungen füge ich bereits in der SQL-Abfrage ein (GROUP_CONCAT),

      Welchen Zweck soll die Gruppierung erfüllen? Warum fragst du nciht einfach nur die Daten ab und formatierst sie im abfragenden Programm?

      Meine Idee war es, gleich bei der SQL-Abfrage die Formatierung vorzunehmen (eigentlich hatte ich sogar vier Teil-Abfragen):
      Datum vor $heute und gebucht: Uhrzeit ohne Link, mit Text gebucht
      Datum vor $heute und nicht gebucht: Uhrzeit durchgestrichen
      Datum ab $heute und gebucht: Uhrzeit ohne Link, mit Text gebucht
      Datum ab $heute und nicht gebucht: Uhrzeit als Link

      Mehrere Termine pro Kalendertag mit GROUP_CONCAT zusammengefasst.

      Jetzt hab ich mal nur eine SQL-Abfrage: Datum ab $heute und egal ob gebucht oder nicht.
      Formatierung via Abfrage und replace-Funktion in PHP.
      (Auf Datum vor $heute hab ich mal verzichtet.)

      Kann man da nochmals eine GROUP_CONCAT über beide Abfragen machen?

      Das kann ich jetzt nicht mit Bestimmtheit sagen, aber wenn, dann muss die unionisierte Abfrage als Subselect in einer FROM-Klausel landen, woraufhin du dann wieder GROUP BY etc. anwenden kannst. Ob MySQL sowas zulässt, musst du mal dem Handbuch entnehmen oder probieren.

      Allgemein scheint mir das aber nicht der richtige Weg zu sein. Du hast es jetzt schon komplizierter als nötig (gemäß meinem Bauchgefühl beim groben Überfliegen des Problems). Eine Gruppierung ohne abenteuerliche GROUP_CONCATs bekommt man auch im abfragenden Programm hin. Recherche-Stichwort: Gruppenwechsel.

      @Gruppenwechsel: http://www.php.de/wiki-php/index.php/Gruppenbruch_(Standardverfahren)
      Da blick ich noch nicht so recht durch ... zumindest nicht, wie ich das für mein Problem nutzen könnte.

      Trotzdem Danke!
      Christian.

      1. Tach!

        Meine Idee war es, gleich bei der SQL-Abfrage die Formatierung vorzunehmen (eigentlich hatte ich sogar vier Teil-Abfragen):

        Und versuchst das alles in eine Abfrage zu pressen, die dann ein schwer wartbares Monster wird ...

        @Gruppenwechsel: http://www.php.de/wiki-php/index.php/Gruppenbruch_(Standardverfahren)
        Da blick ich noch nicht so recht durch ... zumindest nicht, wie ich das für mein Problem nutzen könnte.

        Geht vielleicht auch ohne, das musst du letztlich entscheiden. Ich dachte an einen Gruppenwechsel pro Tag. Alles an einem Tag bildet eine Gruppe. Wenn der Tag wechselt, muss das in der Darstellung berücksichtigt werden. Andererseits kannst du auch ein Array mit allen 28..31 Tagen (als Keys) anlegen und mit einfachem Durchlaufen durch die Ergebnismenge die Datensätze in dieses Tages-Array einsortieren.

        dedlfix.