mysql Vereinsmitglieder

Ezi

Grünschnabel
Hallo,

bei MYSQL und PHP bin ich noch Anfänger, deshalb brauche ich Hilfe bei folgendem Problem:
für meinen Kegelverein bastle ich gerade an einer Website und bin nun an den Mitgliedern dran.
Hier habe ich ein MYSQL Datenbank erstellt u. a. mit den Tabellen
member, mitgliedsdauer

member hat die Spalten id, nickname, nachname, geburtstag, sterbedatum

mitgliedsdauer hat die Spalten member_id, eintritt, austritt, eintritt2, austritt2, eintritt3, austritt3, gesamt

Da einige Mitglieder mehrmals aus- und wieder eingetreten sind, gibt es eben die Spalten mit eintritt2, austritt2, eintritt3…


Um die Mitglieder in einer Tabelle auf der Website aufzulisten, habe ich folgenden Code:


<?php

try {

$verbindung = new PDO("mysql:host=localhost;dbname=datenbank;charset=utf8", "root", "");

}

catch(Exception $fehler) {

print $fehler->getMessage();

}

$sqlBefehl = "SELECT `nickname`, `nachname`, `eintritt`, `austritt`, `gesamt` from `member`, `mitgliedsdauer`

where `id` = `member_id`";

$abfrage = $verbindung->prepare($sqlBefehl);

$abfrage->execute();

$ergebnismenge = $abfrage->fetchAll();

?>

<table>
<thead>
<tr>
<td>Vorname</td>
<td>Nachname</td>
<td>Eintritt</td>
<td>Austritt</td>
</tr>
</thead>
<tbody>
<!-- PURES HTML ENDE -->

<!-- LOOP MIT PHP UND HTML TAGS PER ECHO -->

<?php foreach($ergebnismenge as $zeile) : ?>

<tr>
<td><?php echo $zeile['nickname']; ?></td>
<td><?php echo $zeile['nachname']; ?></td>
<td><?php $eintritt = new DateTime($zeile['eintritt']); echo $eintritt->format('d.m.Y')."<br />";?></td>
<td><?php $austritt = new DateTime($zeile['austritt']); echo $austritt->format('d.m.Y')."<br />";?></td>
</tr>

<?php endforeach; ?>

<!-- ENDE PHP LOOP -->

<!-- PURES HTML -->
</tbody>
</table>

<!-- HTML ENDE -->



Dies funktioniert soweit gut. Es wird folgendes ausgeworfen:

VornameNachnameEintrittAustritt
ArturGöggel05.10.196321.11.1964
FelixFischer05.10.196327.06.1964
UlbrichtSchröder05.10.196321.12.1970
HelmutBlum05.10.196312.12.1964
Kal-HeinzMüller05.10.196331.05.1964
WalterHuber05.10.196305.01.2017





Nun möchte ich aber in einer extra Spalte die Dauer der Vereinszugehörigkeit anzeigen lassen - am liebsten mit Tagen, Monaten, Jahren. Und da scheitere ich daran.
Wenns zu kompliziert werden sollte, wäre ich auch nur mit Jahren zufrieden :)
Im Netz finde ich zwar wie man das Alter bzw. die Dauer berechnen lassen kann, aber ich bekomms einfach nicht hin ☹

Als einzelner Befehl bei phpAdmin habe ich erfolgreich das versucht:

SELECT TIMESTAMPDIFF(YEAR, eintritt, austritt) AS alter_jahr

from mitgliedsdauer



hier wirft er mir die Jahre aus – aber ich bekomms im sql-befehl bzw. php leider nicht hin.



Und komplizierter wird es ja wenn einer ausgetreten ist und wieder dabei ist.

Kann mir da jemand weiterhelfen?
Vielen lieben Dank
Gruß
Ezi
 
Hallo Ezi!
Da einige Mitglieder mehrmals aus- und wieder eingetreten sind, gibt es eben die Spalten mit eintritt2, austritt2, eintritt3…
Besser nur ein Mal eintritt und austritt und für jedes Intervall einen eigenen Datensatz anlegen. Dann kannst Du die gesamte Dauer der Mitgliedschaft für jedes Mitglied relativ einfach ermitteln:
Code:
SELECT
    member_id,
    SUM(TIMESTAMPDIFF(DAY, eintritt, IFNULL(austritt,CURDATE()))) AS dauer
FROM einaustritt
GROUP BY member_id
Oder für ein spezifisches Mitglied:
Code:
SELECT
    member_id,
     SUM(TIMESTAMPDIFF(DAY, eintritt, IFNULL(austritt,CURDATE()))) AS dauer
FROM einaustritt
WHERE member_id=10
Das Aufschlüsseln nach Tagen, Monaten und Jahren gestaltet sich nicht so einfach weil die Anzahl der Tage in einem Monat variabel ist. In das Problem bin ich jetzt nicht eingestiegen.
 
Zuletzt bearbeitet:
Was das aufdröseln einer Zeitspanne in Tage, Monate, Jahre betrifft:
MySQL PERIOD_DIFF() Function
MySQL DATEDIFF() Function

Wenn du es exakt haben willst/musst:
1) Addiere 1 Tag zum Austrittsdatum. Wird "neues" Austrittsdatum
2) bilde die Monatsdifferenz (PERIOD_DIFF-Funktion)
3) Nimm den tatsächlichen Tag der beiden Tage, ziehe den "Austritt-Tag" vom "Eintritts-Tag" ab
(Bsp. ET=20.02.2024 - AT=28.06.2024) --> "28-20= 8"
Ist das Ergebnis >=0, alles gut
Ist das Ergebnis negativ wirds knifflig:
4) reduziere Monate (aus PERIOD_DIFF) um 1
5) Finde den letzten Tag des Monats des Eintritts-Datums
(Bsp. ET = 22.01.2024 - AT=15.06.2024) --> "15-22"=-7 --> 22.01.2024 ist letzter Tag des Eintritts-Monats der 31ste.
6) Nimm diesen letzten tag und subtrahiere ihn vom tatsächlichen Tag des Eintritts ab,
--> 31-22 = 9
7) Addiere jetzt den Tag des Austrittsdatums hinzu --> 9+15 = 24

Anbei Fiddle für deinThema (habs jetzt aber nicht nachgerechnet):
DB Fiddle - SQL Database Playground

Für die Jahre rechnest du einfach Monatsergebnis ganzzahlig geteilt durch 12, Monatsergebnis modulo 12 für die überhängenden Monate

Für das Aufdröseln einer Zeitspanne habe ich hier im Forum mal was für SQLite geschrieben.
Lässt sich sicher nach MySQL übersetzen:
[SQLite-Tutorial] Jahre, Monate und Tage zwischen zwei Tagen

Wenn du jedoch die "Gesamtdauer der Mitgliedschaft" über die "Unterbrechungen" hinweg ausrechnen willst, gibts auch ne Lösung, aber die ist konzeptionell nicht einfach zu verstehen.
Ich geb dir nen Hinweis: Oben haben wir nur Zeitspannen ausgerechnet.
Für die Gesamtdauer der Mitgliedschaft, nimmst du als Eintrittstag den "ältesten" Eintrittstag und addierst einfach alles auf (Tage, Monate, Jahre usw.) bis ein "Enddatum" erscheint. Dann den Algorithmus von oben darauf anwenden
Es kann/wird aber definitiv eine Unschärfe geben: Schaltjahre
Hier für die "Gesamtdauer" (jedoch eben mit Unschärfe)
DB Fiddle - SQL Database Playground

EDIT: ich denke ich hab ne Möglichkeit gefunden, diese Unschärfe zu eliminieren, müsste aber nochmal tiefer darüber nachdenken. Bin mir nicht sicher, aber es müsste über eine rekursive Aufaddierung der "Einzel-Werte" (Jahre, Monate, Tage) der einzelnen Zeitspannen gehen
 
Zuletzt bearbeitet:
Jepp.
DB Fiddle - SQL Database Playground

Unschärfe bewiesen.
Im Fiddle-Beispiel habe ich "Fritz Müller" mit folgenden Daten
Eintritt=01.01.2013 - Austritt=31.12.2015
Eintritt=01.01.2017 - Austritt=31.12.2019
Eintritt=01.01.2021 - Austritt=31.12.2023

Jeder normale Mensch würde sagen, dass Fritz Müller exakt 0 Tage, 0 Monate, 3x3 (=9) Jahre Mitglied war
Wendet man aber o.g. Algorithmus darauf an, kommt folgendes Ergebnis heraus
29 Tage, 11 Monate, 8 Jahre
Warum?
Da ich das älteste Eintrittsdatum als Startpunkt wähle, und dort 9x365 Tage dazu addiere,
lande ich nämlich nicht beim 31.12.2021, sondern beim 29.12.2021:
Ich habe nämlich zwei Schaltjahre drin (2016 und 2020).

Betrifft sowohl meinen, als auch Semper's Algorithmus, da Semper auch die Summe der Tagesdifferenzen bildet

Bin mir jetzt sogar sicher, dass wenn man (rekursiv?) die "Einzel-Werte" der Zeitspannen (beginnend mit Jahren, dann Monate, dann Tage) zum Startdatum dazu addiert, dann der "richtige" Wert heraus kommt
 
super, hat mir schon viel geholfen. Aber nun habe ich ein weiteres Problem:
die Daten rufe ich per phpAdmin ab:

PHP:
<?php
 // Verbindung zur Datenbank über der PDO()-Funktion aufbauen
// (Host, Datenbank, Charset, Benutzer, Passwort)

try {
$verbindung = new PDO("mysql:host=localhost;dbname=kcr;charset=utf8", "root", "");
}
catch(Exception $fehler) {
    print $fehler->getMessage();
}
$sqlBefehl = "SELECT
    nickname, nachname, eintritt, max( austritt ) AS austritt,
    SUM(TIMESTAMPDIFF(DAY, eintritt, IFNULL(austritt, CURDATE()))) AS dauer  
FROM mitgliedsdauer, member
where id=member_id
GROUP BY member_id
ORDER BY dauer DESC";
$abfrage = $verbindung->prepare($sqlBefehl);
$abfrage->execute();
$ergebnismenge = $abfrage->fetchAll();

?>
<table>
 <thead>
  <tr>
   <td>Kegler</td>
   <td>Nachname</td>
   <td>Eintrittsdatum</td>
   <td>Mitglied bis</td>
      <td>Vereinszugehörigkeit in Tagen</td>
  </tr>
 </thead>
  <tbody>
<!-- PURES HTML ENDE -->

<!-- LOOP MIT PHP UND HTML TAGS PER ECHO -->
  
  <?php foreach($ergebnismenge as $zeile) : ?>
    <tr>
     <td><?php echo $zeile['nickname']; ?></td>
     <td><?php echo $zeile['nachname']; ?></td>
     <td><?php $eintritt = new DateTime($zeile['eintritt']);
                    echo $eintritt->format('d.m.Y')."<br />";?></td>
    <td><?php $austritt = new DateTime($zeile['austritt']);
                    echo $austritt->format('d.m.Y')."<br />";?></td>              
     <td><?php echo $zeile['dauer']; ?></td>     
    </tr>
  <?php endforeach; ?>
<!-- ENDE PHP LOOP -->

<!-- PURES HTML -->
 </tbody>
</table>
<!-- HTML ENDE -->


damit bekomme ich alle geforderten Ergebnisse :)
Will ich die Aber auf der Website ausgeben, erscheint immer nur 1 Datensatz :-(

Hier der Code dazu:

PHP:
<?php
  $host_name = 'db0000000000.hosting-data.io';
  $database = 'dbs00000000';
  $user_name = 'dbu0000000';
  $password = 'xxxxxxxxxxxxxxx!';
  $dbh = null;

  try {
    $dbh = new PDO("mysql:host=$host_name; dbname=$database;", $user_name, $password);
  }
    catch (PDOException $e) {
    echo "Fehler!:" . $e->getMessage() . "<br/>";
     die();     
  }
?>
 <?php 
$sqlBefehl = 'SELECT
    id, nickname, nachname, geburtstag, eintritt, max( austritt ) AS austritt,
    SUM(TIMESTAMPDIFF(YEAR, eintritt, IFNULL(austritt, CURDATE()))) AS dauer_jahre,
    SUM(TIMESTAMPDIFF(DAY, eintritt, IFNULL(austritt, CURDATE()))) AS dauer  
FROM mitgliedsdauer, member
where id=member_id
GROUP BY member_id
ORDER BY dauer ASC';
$abfrage = $dbh->prepare($sqlBefehl);
$abfrage->execute();
$ergebnismenge = $abfrage->fetchAll();

?>
  
  <?php foreach($ergebnismenge as $zeile) : ?>
  
  <?php endforeach; ?>
<table class="tableizer-table colright">
 <thead>
  <tr class="tableizer-firstrow">
   <th>Nr.</th>
    <th>Kegler</th>
    <th>Nachname</th>
    <th>Eintrittsdatum</th>
    <th>Mitglied bis</th>
      <th>Vereinszugehörigkeit in Jahren</th>
      <th>Vereinszugehörigkeit in Tagen</th>
  </tr>
 </thead>
  <tbody>
<!-- PURES HTML ENDE -->

<!-- LOOP MIT PHP UND HTML TAGS PER ECHO --><tr>
     <td><?php echo $zeile['id']; ?></td>
     <td><?php echo $zeile['nickname']; ?></td>
     <td><?php echo $zeile['nachname']; ?></td>
     <td><?php $eintritt = new DateTime($zeile['eintritt']);
                    echo $eintritt->format('d.m.Y')."<br />";?></td>
    <td><?php $austritt = new DateTime($zeile['austritt']);
                    echo $austritt->format('d.m.Y')."<br />";?></td>
     <td><?php echo $zeile['dauer_jahre']; ?></td>                   
     <td><?php echo $zeile['dauer']; ?></td>     
    </tr><!-- ENDE PHP LOOP -->

<!-- PURES HTML -->
 </tbody>
</table>
<!-- HTML ENDE -->
 
Zuletzt bearbeitet von einem Moderator:
Ist doch logisch.
Du hast einen leeren Loop
PHP:
  <?php foreach($ergebnismenge as $zeile) : ?>
   
  <?php endforeach; ?>
Und später erst gibst du die Zeile aus. In dem Fall die Letzte Ziele, da du mit dem Loop ja schon durch bist.

So sollte es sein:
PHP:
  <tbody>
<!-- PURES HTML ENDE -->
  <?php foreach($ergebnismenge as $zeile) : ?>
 
<!-- LOOP MIT PHP UND HTML TAGS PER ECHO --><tr>
     <td><?php echo $zeile['id']; ?></td>
     <td><?php echo $zeile['nickname']; ?></td> 
     <td><?php echo $zeile['nachname']; ?></td>
     <td><?php $eintritt = new DateTime($zeile['eintritt']);
                    echo $eintritt->format('d.m.Y')."<br />";?></td>
    <td><?php $austritt = new DateTime($zeile['austritt']);
                    echo $austritt->format('d.m.Y')."<br />";?></td>
     <td><?php echo $zeile['dauer_jahre']; ?></td>                    
     <td><?php echo $zeile['dauer']; ?></td>      
    </tr><!-- ENDE PHP LOOP -->
 
  <?php endforeach; ?>
<!-- PURES HTML -->
 </tbody>
 
Dankeschön. Das mit dem leeren Loop habe ich übersehen :-(
Komisch, denn bei phpAdmin ist der Code richtig. Kopiere ich den Code in MOBIRISE (mein Programm zum Erstellen meiner Website), wird dies immer automatisch abgeändert.
Habe dies aber nun anders lösen können. Dankeschön!
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück