• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

[ERLEDIGT] Per JOIN mehrere Felder in einem zusammenfassen

Hi,
folgende Situation:
Es geht um die Verwaltung von Sportergebnissen, bei denen einige als Mannschaft erreicht wurden (ergo mit mehreren Athleten).
Nun habe ich mehrere Tabellen in der mysql Datenbank:

Eine für die Ergebnisse, in die aber nur die Kürzel der Sportlernamen eingetragen werden. Dann noch die Tabelle für die Athleten, in denen ihre vollen Namen und die besagten Kürzel gespeichert wurden. Das Verknüpfen mit LEFT JOIN bei Einzeldisziplinen ist ja kein Problem, Ausgabe sieht dann vereinfacht so aus (fehlen jetzt natürlich daten wie Disziplin, Ort, Leistung etc.):
skuerzelskuerzel1skuerzel2skuerzel3skuerzel5skuerzelathlet
hmhmHans Mustermann

So, die Doppelung der Kürzel bekomme ich mit einem NATURAL JOIN weg, aber das ist jetzt nicht das Thema...

Wenn dann allerdings mehrere Sportler dazukommen, sieht das so aus:
skuerzelskuerzel1skuerzel2skuerzel3skuerzel4skuerzelathlet
hmmmkmdmhmHans Mustermann

Das Ziel von mir ist aber (logischerweise), dass alle vollen Namen der beteiligten Sportler ausgegeben werden. Entweder alle in der Spalte "athlet" hintereinander, oder halt in Extraspalten (athlet1 usw.)

Wie kann ich das realisieren? Bzw. ist JOIN schonmal ein richtiger Ansatz, oder gehe ich da in eine falsche Richtung?
Achja, ich nutze mysql, nicht mysqli...
 
Werbung:
Habe eine (vermutlich etwas umständliche) Lösung gefunden:
Ich habe jeweils für die verschiedenen skuerzel-Varianten eine entsprechende neue Athleten-Tabelle erstellt. Habe jetzt also 5 Tabellen mit dem gleichen Inhalt nur anderen Spaltenbezeichnungen...
 
Hi Trüffelkrieger,

das ist aus verschiedenen Gründen nicht sinnvoll. Aber der Ansatz ist gut. Statt der fünf Tabellen kannst du auch einfach eine nehmen und die über verschiedene Aliase mehrfach verwenden. Das erspart dir, fünf Tabellen parallel zu pflegen.
Code:
...
FROM
  ...
     atlet as a1,
     atlet as a2,
     atlet as a3,
     atlet as a4,
     atlet as a5
WHERE
    a1.kuerzel = skuerzel1
AND
    a2.kuerzel = skuerzel2
...
Habs nicht getestet. Aber wenn es mit mehreren Tabellen geht, müsste es mit mehreren Aliasen auch hinhauen.
Unabhängig davon würde ich dir für den weiteren Einstieg ins Thema Datenbanken raten, mal was zum Thema Normalisierung zu lesen. (Hätte ich auch viel früher tun sollen.)
Viel Erfolg!
B.
 
Werbung:
Vielen Dank für den Hinweis, das werde ich mal versuchen.
Zum Thema Normalisierung: Ich habe das schon versucht anzuwenden, eben indem ich nur Kürzel verwende und diese dann aus anderen Tabellen ersetze, ids wollte ich da nicht verwenden, da das nicht so gut zu behalten ist, und wenn ich dann jedes mal wieder suchen muss, wer welche id hatte, dann kann ich auch weiter von Hand arbeiten...

Aber ich gebe dir recht, dass ich da noch ein bisschen weiter in die Tiefe gehen muss... :)
 
Du kannst auch mehrere Joins verbinden, musst dann aber mit aliasen Arbeiten.

Beispiel:

Deine Tabellenstruktur:

Ergebniss Tabelle:
Code:
[TABLE="class: data ajax"]
[TR]
[TH]skuerzel[/TH]
[TH]skuerzel1[/TH]
[TH]skuerzel2[/TH]
[TH]skuerzel3[/TH]
[TH]skuerzel4[/TH]
[TH]ergebniss[/TH]
[/TR]
[TR="class: odd"]
[TD="class: inline_edit not_null"]hm[/TD]
[TD="class: inline_edit not_null"]km[/TD]
[TD="class: inline_edit not_null"]rm[/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null"]10 zu 0[/TD]
[/TR]
[TR="class: even"]
[TD="class: inline_edit not_null"]hm[/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null"]km[/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null"]40 zu 12[/TD]
[/TR]
[/TABLE]
Spieler Tabelle:
Code:
[TABLE="class: data ajax"]
[TR]
[TH]kuerzel[/TH]
[TH]Name[/TH]
[/TR]
[TR="class: odd"]
[TD="class: inline_edit not_null"]hm[/TD]
[TD="class: inline_edit not_null"]Hans Mustermann[/TD]
[/TR]
[TR="class: even"]
[TD="class: inline_edit not_null"]km[/TD]
[TD="class: inline_edit not_null"]Kalle Mustermann[/TD]
[/TR]
[TR="class: odd"]
[TD="class: inline_edit not_null"]rm[/TD]
[TD="class: inline_edit not_null"]Ralf Mustermann[/TD]
[/TR]
[/TABLE]

Folgender Join:
Code:
SELECT  `ergebnisse`.`skuerzel` ,  `ergebnisse`.`skuerzel1` ,  `ergebnisse`.`skuerzel2` ,  `ergebnisse`.`skuerzel3` ,  `ergebnisse`.`skuerzel4` ,  `ergebnisse`.`ergebniss` ,  `spieler`.Name,  `spieler1`.Name AS Name1,  `spieler2`.Name AS Name2,  `spieler3`.Name AS Name3,  `spieler4`.Name AS Name4
FROM  `ergebnisse` 
LEFT  JOIN spieler ON  `ergebnisse`.`skuerzel`  =  `spieler`.`kuerzel` 
LEFT  JOIN spieler AS spieler1 ON  `ergebnisse`.`skuerzel1`  =  `spieler1`.`kuerzel` 
LEFT  JOIN spieler AS spieler2 ON  `ergebnisse`.`skuerzel2`  =  `spieler2`.`kuerzel` 
LEFT  JOIN spieler AS spieler3 ON  `ergebnisse`.`skuerzel3`  =  `spieler3`.`kuerzel` 
LEFT  JOIN spieler AS spieler4 ON  `ergebnisse`.`skuerzel4`  =  `spieler4`.`kuerzel`
bringt dann folgendes Ergebnis:
Code:
[TABLE="class: data ajax"]
[TR]
[TH]skuerzel[/TH]
[TH]skuerzel1[/TH]
[TH]skuerzel2[/TH]
[TH]skuerzel3[/TH]
[TH]skuerzel4[/TH]
[TH]ergebniss[/TH]
[TH]Name[/TH]
[TH]Name1[/TH]
[TH]Name2[/TH]
[TH]Name3[/TH]
[TH]Name4[/TH]
[/TR]
[TR="class: odd"]
[TD="class: inline_edit not_null"]hm[/TD]
[TD="class: inline_edit not_null"]km[/TD]
[TD="class: inline_edit not_null"]rm[/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null"]10 zu 0[/TD]
[TD="class: inline_edit"]Hans Mustermann[/TD]
[TD="class: inline_edit"]Kalle Mustermann[/TD]
[TD="class: inline_edit"]Ralf Mustermann[/TD]
[TD="class: inline_edit null, align: right"][I]NULL[/I][/TD]
[TD="class: inline_edit null, align: right"][I]NULL[/I][/TD]
[/TR]
[TR="class: even"]
[TD="class: inline_edit not_null"]hm[/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null"]km[/TD]
[TD="class: inline_edit not_null nowrap"][/TD]
[TD="class: inline_edit not_null"]40 zu 12[/TD]
[TD="class: inline_edit"]Hans Mustermann[/TD]
[TD="class: inline_edit null, align: right"][I]NULL[/I][/TD]
[TD="class: inline_edit null, align: right"][I]NULL[/I][/TD]
[TD="class: inline_edit"]Kalle Mustermann[/TD]
[TD="class: inline_edit null, align: right"][I]NULL[/I][/TD]
[/TR]
[/TABLE]

Meinst du sowas?
Ich denke das ist ein guter Ansatz

MfG
 
Werbung:
Auch nochmal zum Thema Normalisierung. Wir sollten hier nicht allzuviel auf mein nicht wahnsinnig fundiertes Halbwissen in diesem Bereich geben, aber eine Normalisierung hätte meines Ermessens weit gravierendere Auswirkungen auf dein Datenbanksystem, als die Vergabe von Integer-Werten für die IDs. Eigentlich bräuchtest du drei Tabellen:
1. Eine Tabelle, die Spiele auflistet.
2. Eine Tabelle, die Spieler auflistet.
3. Eine Tabelle, die zwei Felder hat: eine für IDs der Spiele, eine für die IDs der Spieler. (Eigentlich noch ein drittes Feld, denn auch hier bekommt jeder Eintrag nochmal ne eigene ID.) Für jedes Spiel hättest du in deinem Fall 5 Einträge in Tabelle 3 und einen in Tabelle 1.
Hätte den Vorteil, dass du flexibler bist, was die Mannschaftsgröße betrifft. (Gibt ja auch Sportarten mit größeren oder kleineren Teams.)
Ob IDs tatsächlich Zahlen sein müssen, weiß ich gar nicht so genau. In dem Moment, wo Tabellen über ein Skript gefüllt und ausgelesen werden, sind Integer-Werte aber sicher sinnvoll. Und was die IDs bedeuten muss man dann als menschlicher Betrachter der Datenbank dann gar nicht mehr wissen ...
 
Es geht bei dem Projekt um Leichtathletik, größere Mannschaften als 5 gibts da meines Wissens nicht, weshalb ich da nicht variabel nach oben sein muss.
 
So, dass Problem mit den 5 gleichen Tabellen lässt mich nicht los... Ich habe nun einen Ansatz imt Aliasen hinbekommen, der sieht wie folgt aus:
PHP:
SELECT DISTINCT * FROM ergebnisse
JOIN athleten as a1 ON ergebnisse.skuerzel = a1.skuerzel
JOIN athleten as a2 ON ergebnisse.skuerzel1 = a2.skuerzel
JOIN athleten as a3 ON ergebnisse.skuerzel2 = a3.skuerzel
JOIN athleten as a4 ON ergebnisse.skuerzel3 = a4.skuerzel
JOIN athleten as a5 ON ergebnisse.skuerzel4 = a5.skuerzel
Die Ausgabe in phpMyAdmin ist auch voll zufriedenstellend. Sobald eine Mannschaft am Start war, werden deren Namen auch komplett ausgegeben... Das Problem ist, dass es logischerweise so aussieht:
ss1s2s3s4sajsajsajsajsaj
fbfbF. B.90
fbptclfbF. B.90ptP. T.90clC. L.90


  • s = skuerzel
  • s1 = skuerzel1 usw.
  • a = Athlet (voller Name)
  • j = Jahrgang

Nun habe ich zwar alle Namen in der Zeile, aber sie werden durch die gleichen Spaltennamen beschrieben, was bei der Ausgabe ein Problem darstellt. Ich hatte versucht, die Tabellenspalten mittels PHP so anzusprechen, wie das in mySql auch möglich ist (Tabellenname.Spaltenname):
PHP:
require_once ('config-statistik.php');

$sql = "SELECT DISTINCT * FROM ergebnisse
JOIN athleten as a1 ON ergebnisse.skuerzel = a1.skuerzel
JOIN athleten as a2 ON ergebnisse.skuerzel1 = a2.skuerzel
JOIN athleten as a3 ON ergebnisse.skuerzel2 = a3.skuerzel
JOIN athleten as a4 ON ergebnisse.skuerzel3 = a4.skuerzel
JOIN athleten as a5 ON ergebnisse.skuerzel4 = a5.skuerzel
JOIN disziplinen ON ergebnisse.dkuerzel= disziplinen.dkuerzel
JOIN altersklassen ON ergebnisse.akuerzel = altersklassen.akuerzel
WHERE ergebnisse.akuerzel='mju20'
AND jahr=12
ORDER BY
CASE
WHEN ergebnis NOT LIKE '' THEN disziplinen.reihenfolge END ASC,
CASE WHEN ergebnis LIKE '%m' THEN ergebnis END DESC,
CASE WHEN ergebnis LIKE '%sec%' THEN ergebnis END ASC,
CASE WHEN ergebnis LIKE '%min%' THEN ergebnis END ASC,
CASE WHEN ergebnis LIKE '%Std%' THEN ergebnis END ASC,
CASE WHEN ergebnis LIKE '%Pkt%' THEN ergebnis END DESC";
$db_erg = mysql_query( $sql );
if ( ! $db_erg )
{
die('Ungültige Abfrage: ' . mysql_error());
}
echo '<table>';
$wertalt = "";
while ($zeile = mysql_fetch_array( $db_erg, MYSQL_ASSOC))
{
echo "<tr>";

if( $wertalt != $zeile['disziplin' ] ) {
  echo "<td>". $zeile['disziplin'] . "</td>";
 }
 else{
    echo"<td></td>";
 }
 $wertalt = $zeile['disziplin'];

echo "<td>". $zeile['ergebnis'] . "</td>";
echo "<td>". $zeile['a1.athlet'];
if($zeile['a5.athlet'] != ''){
    echo "<br />". $zeile['a2.athlet'];
    echo "<br />". $zeile['a3.athlet'];
    echo "<br />". $zeile['a4.athlet'];
    echo "<br />". $zeile['a5.athlet'];
}elseif($zeile['a4.athlet'] != ''){
    echo "<br />". $zeile['a2.athlet'];
    echo "<br />". $zeile['a3.athlet'];
    echo "<br />". $zeile['a4.athlet'];
}elseif($zeile['a3.athlet'] != ''){
    echo "<br />". $zeile['a2.athlet'];
    echo "<br />". $zeile['a3.athlet'];
}
echo "</td>";
echo "<td>";
if($zeile['athlet2'] == ''){
    echo $zeile['jahrgang'];
}
echo"</td>";
echo "<td>".$zeile['ort'].", " .$zeile['tag'].".".$zeile['monat'] . "</td>";

echo "</tr>";
}
echo "</table>";
mysql_free_result( $db_erg );
Das Ergebnis ist eine weiße Seite, keine Fehlermeldung. Ich muss den Spalten ja theoretisch ebenfalls Aliase zuweisen können, allerdings scheiter ich da, wie das sozusagen fünfmal mit der gleichen Saplte gehen soll.

Ich hoffe, dass das Problem verständlich beschrieben ist und jemand einen Lösungsansatz für mich.
 
Werbung:
Das ist jetzt nur so auf Verdacht. Habe mich gerade nicht wirklich reingedacht und auch nicht alles gelesen. Aber das hier könnte was bringen:

Code:
JOIN
        athleten AS a
ON 
    (
        ergebnisse.skuerzel = a.skuerzel
        OR ergebnisse.skuerzel1 = a.skuerzel 
        OR ergebnisse.skuerzel2 = a.skuerzel
        OR ergebnisse.skuerzel3 = a.skuerzel
        OR ergebnisse.skuerzel4 = a.skuerzel
    )
 
Hi mermshaus,
das hilft mir nicht wirklich (oder ich versteh's nicht genau). Da bekomme ich in der Ausgabe nur die Ergebnisse, bei denen nur ein Sportler gestartet ist.
 
Ah, sorry. Ich habe es falsch interpretiert. Dachte, dass ein Athlet sozusagen an einer von fünf Positionen spielen könnte und du alle Spiele eines Athleten haben willst. Oder so.

Aliase müssten theoretisch so klappen:

Code:
SELECT DISTINCT
        a1.athlet AS a1athlet,
        a2.athlet AS a2athlet,
        a3.athlet AS a3athlet,
        a4.athlet AS a4athlet,
        a5.athlet AS a5athlet,
        ...

FROM
        ergebnisse
...

Kannst du unkompliziert einen DB-Dump mit Schema (CREATE Statements usw.) und Testdaten posten?
 
Werbung:
Hier mal ein kleiner Auszug:
Code:
CREATE TABLE `altersklassen` (
  `akuerzel` varchar(6) collate latin1_german1_ci NOT NULL,
  `altersklasse` varchar(40) collate latin1_german1_ci NOT NULL,
  `reihenfolge` int(2) NOT NULL,
  PRIMARY KEY  (`akuerzel`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci;

CREATE TABLE `athleten` (
  `skuerzel` varchar(5) collate latin1_german1_ci NOT NULL,
  `athlet` varchar(35) collate latin1_german1_ci NOT NULL,
  `jahrgang` varchar(2) collate latin1_german1_ci NOT NULL,
  PRIMARY KEY  (`skuerzel`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci;


CREATE TABLE `disziplinen` (
  `dkuerzel` varchar(8) collate latin1_german1_ci NOT NULL,
  `disziplin` varchar(40) collate latin1_german1_ci NOT NULL,
  `reihenfolge` int(2) NOT NULL,
  PRIMARY KEY  (`dkuerzel`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci;

CREATE TABLE `ergebnisse` (
  `id` int(5) NOT NULL auto_increment,
  `akuerzel` varchar(6) collate latin1_german1_ci NOT NULL,
  `dkuerzel` varchar(12) collate latin1_german1_ci NOT NULL,
  `ergebnis` varchar(12) collate latin1_german1_ci NOT NULL,
  `skuerzel` varchar(5) collate latin1_german1_ci NOT NULL,
  `skuerzel1` varchar(5) collate latin1_german1_ci NOT NULL,
  `skuerzel2` varchar(5) collate latin1_german1_ci NOT NULL,
  `skuerzel3` varchar(5) collate latin1_german1_ci NOT NULL,
  `skuerzel4` varchar(5) collate latin1_german1_ci NOT NULL,
  `ort` varchar(30) collate latin1_german1_ci NOT NULL,
  `tag` varchar(6) collate latin1_german1_ci NOT NULL,
  `monat` varchar(2) collate latin1_german1_ci NOT NULL,
  `jahr` varchar(2) collate latin1_german1_ci NOT NULL,
  `vereinsrekord` varchar(1) collate latin1_german1_ci NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=882 DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci AUTO_INCREMENT=882 ;


INSERT INTO `altersklassen` VALUES ('mju20', 'Männliche&nbsp;Jugend&nbsp;U20', 2);

INSERT INTO `athleten` VALUES ('mm', 'Max&nbsp;Mustermann', '93');
INSERT INTO `athleten` VALUES ('mam', 'Maximilian&nbsp;Muster', '94');
INSERT INTO `athleten` VALUES ('pm', 'Peter&nbsp;Muster', '94');
INSERT INTO `athleten` VALUES ('ff', 'Fred&nbsp;Feuer', '94');
INSERT INTO `athleten` VALUES ('jm', 'Joachim&nbsp;Muster', '94');

INSERT INTO `disziplinen` VALUES ('200h', '200&nbsp;m&nbsp;Hürden', 38);
INSERT INTO `disziplinen` VALUES ('4x100', '4&nbsp;x&nbsp;100&nbsp;m', 43);
INSERT INTO `disziplinen` VALUES ('3x800', '3&nbsp;x&nbsp;800&nbsp;m', 46);


INSERT INTO `ergebnisse` VALUES (280, 'mju20', '200h', '25,9 sec.', 'mam', '', '', '', '', 'Wathlingen', '31', '04', '12', 'e');
INSERT INTO `ergebnisse` VALUES (619, 'mju20', '3x800', '6:45,2 min.', 'jm', 'pm', 'ff', '', '', 'Garbsen', '06', '04', '12', '');
INSERT INTO `ergebnisse` VALUES (710, 'mju20', '4x100', '45,28 sec.', 'mam', 'mm', 'ff', 'jm', '', 'Celle', '12', '07', '12', 'e');

Habe jetzt mal ein paar Disziplinen rausgegriffen, die eine verschiedene Anzahl Sportler haben, wenn dir das zu wenige sind, kann ich dir auch mehr posten.

Vielen Dank schonmal für die Mühen!
 
Zuletzt bearbeitet:
Mit den Daten funktioniert leider glaube ich die lange Query aus einem deiner letzten Beiträge nicht. (Und in der vorletzten Zeile fehlt hinten bei der '12, ein Anführungszeichen. Das könntest du vielleicht noch editieren.) Aber mein Vorschlag aus #12 müsste funktionieren. Ich weiß auch nicht, wie es in nur einer Query groß eleganter geht.

Vielleicht auf eine zweite Query ausweichen, die per WHERE `skuerzel` IN (<Liste von Strings aller Kürzel aus der ergebnis-Zeile>) die Athleten-Einträge bezieht. Ist etwas lesbarer, sind aber mehr Queries. Zudem nutzt du da MyISAM, kannst also meines Wissens keine Transaktionen verwenden. Na ja.
 
Aber wie kann ich denn den Join dann nach dem Code aus #12 noch einbauen? Denn die Daten habe ich dann vorher ja schon ausgelesen (jedenfalls die aus der Athleten Tabelle). Aber ich muss die Namen ja noch in die Zeilen bekommen.
 
Werbung:
Heute habe ich mich noch einmal intensiver mit meinem Problem beschäftigt, und diese Lösung gefunden, die einwandfrei funktioniert und nur eine Athleten Tabelle benötigt. Vielen Dank an dieser Stelle nochmal für eure Hilfe!
PHP:
SELECT ergebnisse.dkuerzel, ergebnisse.ergebnis, ergebnisse.ort, ergebnisse.tag, ergebnisse.monat, a1.jahrgang, a1.athlet AS athlet1, a2.athlet AS athlet2, a3.athlet AS athlet3, a4.athlet AS athlet4, a5.athlet AS athlet5, altersklassen.altersklasse, disziplinen.disziplin, endungen.endung, CAST(ergebnis AS DECIMAL(12,6)) as ergebnis_nummer FROM ergebnisse
JOIN athleten as a1 ON ergebnisse.skuerzel = a1.skuerzel
JOIN athleten as a2 ON ergebnisse.skuerzel1 = a2.skuerzel
JOIN athleten as a3 ON ergebnisse.skuerzel2 = a3.skuerzel
JOIN athleten as a4 ON ergebnisse.skuerzel3 = a4.skuerzel
JOIN athleten as a5 ON ergebnisse.skuerzel4 = a5.skuerzel 
JOIN disziplinen ON ergebnisse.dkuerzel= disziplinen.dkuerzel
JOIN altersklassen ON ergebnisse.akuerzel = altersklassen.akuerzel
JOIN endungen ON disziplinen.endung_kurz = endungen.kurz
WHERE jahr='13'
ORDER BY
CASE WHEN ergebnis NOT LIKE '' THEN altersklassen.reihenfolge END ASC,
CASE WHEN ergebnis NOT LIKE '' THEN disziplinen.reihenfolge  END ASC,
CASE WHEN endung_kurz LIKE 'm' THEN ergebnis_nummer END DESC,
CASE WHEN endung_kurz LIKE 'p' THEN ergebnis_nummer END DESC,
CASE WHEN endung_kurz NOT LIKE 'm' THEN ergebnis_nummer END ASC
 
Zuletzt bearbeitet:
Zurück
Oben