Michaela: Nach Datum und Uhrzeit sortieren / gruppieren

Guten Abend,

vielleicht kann mir der ein oder andere helfen. Ich habe drei Tabellen in meiner Datenbank mit unterschiedlichen Daten. Diese Daten möchte ich nun nach Uhrzeit sortieren.

Das Datum und die Uhrzeit wird so gespeichert:

Alternativ-Text

Eine Abfrage lautet z.B.

function news($mysqli) {
  $stmt = $mysqli->prepare("SELECT id, titel, news, datum, uhrzeit 
			    FROM news ORDER by uhrzeit DESC");
  $stmt->execute();
  $stmt->bind_result($id, $titel, $news, $datum, $uhrzeit);
  $stmt->store_result();
	 	
    if($stmt->num_rows() >  0) {     
	while ($stmt->fetch()){
		$news[] = array( 
			'id' 	  => $id, 
			'titel'   => $titel, 
			'news' 	  => $news,
			'datum'	  => $datum,
			'uhrzeit' => $uhrzeit
		);
	}
	return $news;
  }
}

Muss ich jetzt für jede Tabelle eine Abfrage schreiben oder kann ich alles in einer Abfrage unterbringen?

Meine zweite Frage lautet, wie kann ich die Daten nach Uhrzeit sortieren / gruppieren?

  1. Tach!

    Das Datum und die Uhrzeit wird so gespeichert:

    Alternativ-Text

    Der Feldtyp wäre interessanter. Aus dem Bild kann man nichts weiter entnehmen, außer dass die Daten so aussehen, als ob sie sortierbar sind. Man sieht jedoch nicht, ob es Strings oder DATE- beziehungsweise TIME-Felder sind.

    Muss ich jetzt für jede Tabelle eine Abfrage schreiben oder kann ich alles in einer Abfrage unterbringen?

    Das kann man nicht wirklich beantworten, ohne die Tabellenstruktur und das gewünschte Ergebnis zu kennen. Allgemein kann man nur sagen, dass es Joins und UNION gibt.

    Meine zweite Frage lautet, wie kann ich die Daten nach Uhrzeit sortieren / gruppieren?

    Ich kann mir grad nicht denken, was du auf diese Frage als Antwort hören möchtest, weil wieder das Ziel nicht bekannt ist. Sortiert hast du ja schon in der Beispiel-Query.

    dedlfix.

    1. Hallo,

      Der Feldtyp wäre interessanter. Aus dem Bild kann man nichts weiter entnehmen, außer dass die Daten so aussehen, als ob sie sortierbar sind. Man sieht jedoch nicht, ob es Strings oder DATE- beziehungsweise TIME-Felder sind.

      Die Feldtypen lauten:

      1. für das Datum date
      2. für die Zeit time

      Das kann man nicht wirklich beantworten, ohne die Tabellenstruktur und das gewünschte Ergebnis zu kennen. Allgemein kann man nur sagen, dass es Joins und UNION gibt.

      Ok, ich verstehe. In meiner Datenbank gibt es drei Tabellen.
      Eine heißt news die zweite heißt erinnerungen und die dritte heißt termine

      Alle haben in meiner Auswertung etwas miteinander zu tun. Ich möchte einfach wissen, wann was gemacht wurde. Die Auflistung könnte folgendermaßen aussehen:

      18.12.2015 um 08:00 Uhr – News eingetragen
      18.12.2015 um 08:25 Uhr – Erinnerung bearbeitet
      18.12.2015 um 08:26 Uhr – News eingetragen
      18.12.2015 um 09:25 Uhr – Termin hinzugefügt
      usw..

      Verstehst du was ich meine?

      1. Tach!

        Die Feldtypen lauten:

        1. für das Datum date
        2. für die Zeit time

        Gut, dann kann man darauf bei Bedarf auch die vielen Datums- und Zeit-Funktionen anwenden.

        Eine heißt news die zweite heißt erinnerungen und die dritte heißt termine

        Alle haben in meiner Auswertung etwas miteinander zu tun. Ich möchte einfach wissen, wann was gemacht wurde. Die Auflistung könnte folgendermaßen aussehen:

        Das sieht nach einer Aufgabe für UNION aus. Erstelle zunächst drei einzelne SELECT-Querys, auf jede Tabelle eine, die jeweils ein solches Ergebnis liefern:

        18.12.2015 um 08:00 Uhr – News eingetragen
        18.12.2015 um 08:25 Uhr – Erinnerung bearbeitet
        18.12.2015 um 08:26 Uhr – News eingetragen
        18.12.2015 um 09:25 Uhr – Termin hinzugefügt
        usw..

        Also, da muss ein Datumsfeld, ein Zeitfeld und ein Textfeld mit der jeweiligen Aktion in der Ergebnismenge vorkommen. Und dann kannst du die drei Ergebnismengen vereinigen, indem du zwischen die Querys ein UNION setzt. Dazu kommt noch eine Sortierung und vielleicht noch ein paar Klammern, damit die endgültige Menge sortiert wird und nicht nur eine Teilmenge. Das erzählt dir aber das MySQL-Handbuch im Unterkapitel UNION in der Beschreibung zum SELECT-Statement.

        dedlfix.

        1. Hallo,

          Das sieht nach einer Aufgabe für UNION aus. Erstelle zunächst drei einzelne SELECT-Querys, auf jede Tabelle eine, die jeweils ein solches Ergebnis liefern:

          18.12.2015 um 08:00 Uhr – News eingetragen
          18.12.2015 um 08:25 Uhr – Erinnerung bearbeitet
          18.12.2015 um 08:26 Uhr – News eingetragen
          18.12.2015 um 09:25 Uhr – Termin hinzugefügt
          usw..

          Meinst du in etwa so?

          function tmp_TestAusgabe($mysqli, $Code, $datum, $Code, $datum) {
          	$stmt = $mysqli->prepare("(SELECT id, code, userID, status, datum, uhrzeit 
          					FROM tmp01
          					WHERE userID =?
          					AND datum =?) 
          
          					UNION
          								
          				(SELECT erinnerung_id, erinnerung_userCode, erinnerung_nr, erinnerung_update_d, erinnerung_update_u 
          					FROM tmp02
          					WHERE erinnerung_userCode =?
          					AND erinnerung_update_d =?) ");
          		
          	$stmt->bind_param("ssss", $Code, $datum, $Code, $datum);
          	$stmt->execute();
          	$stmt->bind_result($id, $code, $userID, $status, $datum, $uhrzeit, $erinnerung_id, $erinnerung_userCode, $erinnerung_nr, $erinnerung_update_d, $erinnerung_update_u );
          	$stmt->store_result();
          	 	
          	if($stmt->num_rows() >  0) {     
          		while ($stmt->fetch()){
          			$tmp_Ausgabe[] = array( 
          				'id' 		=> $id, 
          				'code' 		=> $code, 
          				'userID' 	=> $userID,
          				'status' 	=> $status, 
          				'datum' 	=> $datum, 
          				'uhrzeit'	=> $uhrzeit,
          				'erinnerung_id' 		=> $erinnerung_id, 
          				'erinnerung_userCode' 	=> $erinnerung_userCode,
          				'erinnerung_Kdnr' 		=> $erinnerung_nr, 
          				'erinnerung_update_d' 	=> $erinnerung_update_d, 
          				'erinnerung_update_u'	=> $erinnerung_update_u
          			);
          		}
          		return $tmp_Ausgabe;
          	}
          }
          

          Wenn ja, dann erhalte ich folgende Fehlermeldung:
          Fatal error: Call to a member function bind_param() on a non-object

          Lass ich das zweite SELECT weg, erhalte ich auf die erste Tabelle eine schöne Ausgabe

          Wenn du es so nicht meinst, dann verstehe ich nicht was du meinst.

          1. Moin!

            1. Hm. Warum sollte das wie gewünscht funktionieren? Und vor allem, welchen Sinn soll das machen?

            function tmp_TestAusgabe($mysqli, $Code, $datum, $Code, $datum) {
            

            Rufst Du das mit

            $dummy=tmp_TestAusgabe($mysqli, 1, 2, 3, 4)
            

            auf, dann hast Du danach:

            $Code=3;
            $datum=4;
            

            Test:

            <?php
            $dummy=Ausgabe(1,2,3,4);
            function Ausgabe($Code, $datum, $Code, $datum) {
                echo '$Code : ', $Code, "\n";
                echo '$datum: ', $datum, "\n";
            }
            

            exec:

            fastix@trainer:/tmp$ php test.php 
            $Code : 3
            $datum: 4
            

            2.

            $stmt = $mysqli->prepare("(...
                              WHERE userID =?
                              AND datum =?) 
            ...
                              WHERE erinnerung_userCode =?
                             AND erinnerung_update_d =?) ");
            

            Dann bindest Du:

            $stmt->bind_param("ssss", $Code, $datum, $Code, $datum);
            

            Heraus kommt:

            ...
                              WHERE userID ="ssss"
                              AND datum =$Code) 
            ...
                              WHERE erinnerung_userCode =$Code
                             AND erinnerung_update_d =$datum
            

            Ist ein wenig viel. Sortiere mal Deine Daten und werte Fehler aus.

            Jörg Reinholz

            1. Hallo,

              sorry bei euch lernt man überhaupt nichts. Man bekommt nur etwas hingeworfen und gut ist. Ich schau mich weiter um. Schade um die Zeit die ich seit gestern Abend hier verbracht habe.

              1. Moin!

                Schade um die Zeit die ich seit gestern Abend hier verbracht habe.

                **2 Minuten nach dem ich Dir einige Deiner Fehler zeigte hast Du schon patzig reagiert... **

                Schade um die Zeit, die ich damit verbrachte, und den Strom sowie den Speicherplatz, den ich offensichtlich ohne den geringsten Nutzen verschwendete, um Deine sehr individuellen Fehler zu finden und sie Dir zu zeigen.

                Du willst mich sicherlich darüber benachrichtigen, dass in einem anderen Forum jemand Deinen Murks repariert habe. Ich glaube das aber nicht.

                Jörg Reinholz

                1. So eine Arrogante Antwort kann nur von einem aus Kassel kommen!

            2. Tach!

              $stmt->bind_param("ssss", $Code, $datum, $Code, $datum);
              

              Heraus kommt:

              ...
                                WHERE userID ="ssss"
                                AND datum =$Code) 
              ...
                                WHERE erinnerung_userCode =$Code
                               AND erinnerung_update_d =$datum
              

              Du solltest mal das PHP-Handbuch bemühen. Als erster Parameter der Funktion wird jedenfalls keine zu bindende Variable erwartet.

              dedlfix.

              1. Moin!

                Du solltest mal das PHP-Handbuch bemühen. Als erster Parameter der Funktion wird jedenfalls keine zu bindende Variable erwartet.

                Stimmt, da stehen die Typen. Im Ergebnis wird es aber auch nicht besser. Da Sandra aber nichts lernen will, statt dessen hier nur unsachlich herum-motzt will und werde ich deren höchst individuelle Probleme nicht lösen.

                Jörg Reinholz

          2. Tach!

            Meinst du in etwa so?

            Ja, aber nur in etwa.

            Wenn ja, dann erhalte ich folgende Fehlermeldung:
            Fatal error: Call to a member function bind_param() on a non-object

            Du fragst unterwegs nicht einmal nach, ob die Funktionen erfolgreich ausgeführt werden konnten, sondern gehst von schönem Wetter aus und machst einfach weiter, so dass es irgendwann kracht. Die Ursache liegt weiter vorn und wenn du die Hilferufe der Funktionen (sprich ihre Rückgaberwerte) berücksichtigt hättest, wäre dir ein Fehler im SQL-Statement gemeldet worden. Schau mal ins PHP-Handbuch, da ist zu jeder Funktion beschrieben, was im Gut- und im Fehlerfall geliefert wird. Man sollte auch nicht davon ausgehen, dass im Echtbetrieb alles gut geht, wenn im Labor keine Fehler auftraten. Ein Konzept, was im Fehlerfall passieren soll - auch aus der Sicht des Anwenders - gehört zu jeder guten Softwareentwicklung.

            Lass ich das zweite SELECT weg, erhalte ich auf die erste Tabelle eine schöne Ausgabe

            Wenn man zwei Mengen mit UNION zusammenführen möchte, müssen diese beiden Mengen in ihrer Struktur übereinstimmen. Es geht nicht, eine Query mit 6 Ergebnisfeldern und eine mit 5 zu vereinigen. Gegebenenfalls muss ein Dummy selektiert werden. Das kann auch ein Literal, wie Leerstring oder NULL sein.

            dedlfix.

            1. Hallo,

              Wenn man zwei Mengen mit UNION zusammenführen möchte, müssen diese beiden Mengen in ihrer Struktur übereinstimmen. Es geht nicht, eine Query mit 6 Ergebnisfeldern und eine mit 5 zu vereinigen. Gegebenenfalls muss ein Dummy selektiert werden. Das kann auch ein Literal, wie Leerstring oder NULL sein.

              ich habe mein Select etwas erweitert dass auf beiden Seite die gleiche Menge ist

              function tmp_TestAusgabe($mysqli, $Code, $datum) {
              	$stmt = $mysqli->prepare("(SELECT id, code, userID, status, datum, uhrzeit 
              					FROM tmp01
              					WHERE userID =?
              					AND datum =?) 
              
              				UNION
              								
              				(SELECT erinnerung_id, erinnerung_userCode, erinnerung_nr, erinnerung_status, erinnerung_update_d, erinnerung_update_u 
              				FROM tmp02
              				WHERE erinnerung_userCode =?
              				AND erinnerung_update_d =?) ");
              		
              	$stmt->bind_param("ssss", $Code, $datum, $Code, $datum);
              	$stmt->execute();
              	$stmt->bind_result($id, $code, $userID, $status, $datum, $uhrzeit, $erinnerung_id, $erinnerung_userCode, $erinnerung_nr, $erinnerung_status, $erinnerung_update_d, $erinnerung_update_u );
              	$stmt->store_result();
              	 	
              	if($stmt->num_rows() >  0) {     
              		while ($stmt->fetch()){
              			$tmp_Ausgabe[] = array( 
              				'id' 		=> $id, 
              				'code' 		=> $code, 
              				'userID' 	=> $userID,
              				'status' 	=> $status, 
              				'datum' 	=> $datum, 
              				'uhrzeit'	=> $uhrzeit,
              				'erinnerung_id' 	=> $erinnerung_id, 
              				'erinnerung_userCode' 	=> $erinnerung_userCode,
              				'erinnerung_Kdnr' 	=> $erinnerung_nr, 
              				'erinnerung_status'	=> $erinnerung_status,
              				'erinnerung_update_d' 	=> $erinnerung_update_d, 
              				'erinnerung_update_u'	=> $erinnerung_update_u
              			);
              		}
              		return $tmp_Ausgabe;
              	}
              }
              

              Nun bekomme ich zwar viele Fehler ich bekomme aber 72 Datensätze angezeigt. Ein Fehler lautet:

              Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement in

              der zweite Fehler der wiederholt sich in jeder Zeile lautet:
              Notice: Undefined offset: 2

              Ich denke dieses liegt nun an

              $tmp_TestAusgabe = tmp_TestAusgabe($mysqli, $UserCode, $datum);
              if($tmp_Ausgabe > 0) {
              	foreach($tmp_Ausgabeas $array){
              		echo htmlspecialchars($array['uhrzeit']);
              	}
              }
              	else { echo "<p>Abfrage lautet 0</p>"; }
              

              Da ich jetzt mehrere Tabellen habe muss dieser Bereich ebenfalls umgebaut werden, richtig?

              1. Tach!

                Nun bekomme ich zwar viele Fehler ich bekomme aber 72 Datensätze angezeigt. Ein Fehler lautet:

                Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement in

                Die Meldung bemängelt genau das, was ihr Text verlauten lässt. Ein UNION vereint die Mengen sozusagen senkrecht und nicht waagerecht. Waagerecht hingegen würde ein JOIN arbeiten. Anders ausgedrückt, ergeben bei einem UNION beispielsweise 5 Datensätze aus der einen Menge und 3 Datensätze aus der anderen Menge insgesamt 8 Datensätze in der Ergebnismenge. Die Teilmengen werden einfach nacheinander in die Ergebnismenge gelegt. Wenn das nicht dein Ziel ist, und du stattdessen Verknüpfungen zwischen beiden Teilmengen brauchst, dann wäre eine der Join-Arten das Mittel zum Ziel. Beim Join kommt es auf dessen Art an, aber es gibt nie mehr als in diesem Beispiel 5 Datensätze. Es können auch weniger sein, wenn aufgrund der Verknüpfungsbedingungen Datensätze wegfallen.

                Die Fehlermeldung kommt jedenfalls, weil in der Ergebnismenge nur 6 Felder enthalten sind, du aber 12 zu binden versuchst.

                der zweite Fehler der wiederholt sich in jeder Zeile lautet:
                Notice: Undefined offset: 2

                Die Ursache kann ich grad nicht aus dem gezeigten Code erkennen. Schau mal genauer hin, da sollte ja auch eine Zeilennummer ausgegeben werden, die dir die Stelle im Code verrät. Du greifst da jedenfalls auf ein Array-Element zu, das nicht existiert. Kontrollausgaben können helfen, die Wirklichkeit aufzuzeigen, um somit die Differenz zum Wunsch zu erkennen. var_dump() liefert bei jeder Art Wert eine genaue Ausgabe, print_r() hilft bei Array. In beiden Fälle empfiehlt sich ein Blick in die Quelltextansicht des Browsers oder ein <pre> vor der Ausgabe.

                dedlfix.