# [MySQL] Tabellen verknüpfen mit Berechnung



## Zero2000 (3. August 2012)

Hallo

laut suche gibt es ja zu "Tabellen verknüpfen" jede Menge Treffer wovon ich mir die meisten auch angesehen habe und ein bisschen probiert, aber leider ist nichts konkretes zu meinem "Problem" dabei.

Ich habe 2 Tabellen wareneingang und warenausgang, beide sind vom Aufbau her gleich:
id, id_kunde, id_artikel, id_warenart, datum, anzahl
Nun möchte ich das Wareneingänge die dem selben Kunden mit selbem Artikel und selber Warenart bei der Ausgabe zusammengezählt werden. So kann ich dann analog zu den Warenausgängen den Bestand errechnen lassen.
Das ganze realisiere ich mit PHP.

Leider bekomme ich das nicht so recht hin. Laut meinem Code bekomme ich immer alle Wareneingänge zu allen Warenausgängen gegenübergestellt. das passt nicht vorne und nicht hinten.

Hier mal mein Code:

```
SELECT we.id_kunde, we.id_artikel, we.id_warenart, we.datum AS ein_datum, we.anzahl AS ein_anzahl, wa.id_kunde, wa.id_artikel, wa.id_warenart, wa.datum AS aus_datum, wa.anzahl AS aus_anzahl FROM wareneingang AS we LEFT JOIN warenausgang AS wa ON we.id_artikel = wa.id_artikel WHERE we.id_kunde = $kunde
```

Kann mir da jemand einen Tip geben der mich auf den richtigen Weg bringt?

LG
Maik


----------



## Zero2000 (6. August 2012)

Hallo

ohne JOIN klappt das schonmal genauso wie ich es mir vorstelle für die Tabelle wareneingang.

```
SELECT id_kunde, id_artikel, id_warenart, datum, SUM(anzahl) AS ein_anzahl FROM wareneingang WHERE id_kunde = $kunde GROUP BY id_kunde, id_artikel, id_warenart
```
Aber wie bekomme ich nun das äquivalent der Tabelle warenausgang?
Wenn ich eine 2. Abfrage erstelle kennt er ja nicht die Beziehung zwischen den beiden Tabellen.

Wär schön wenn hier einer helfen könnte.

LG
Maik


----------



## Yaslaw (6. August 2012)

Als allererstes muss man das QUery mal in eine Lesbare Form quetschen. Einzeiler sind nur bei sehr kleinen Querystrings lesbar.

```
SELECT 
	we.id_kunde,
	we.id_artikel,
	we.id_warenart,
	we.datum AS ein_datum,
	we.anzahl AS ein_anzahl,
	wa.id_kunde,
	wa.id_artikel,
	wa.id_warenart,
	wa.datum AS aus_datum,
	wa.anzahl AS aus_anzahl
FROM 
	wareneingang AS we 
	LEFT JOIN warenausgang AS wa 
		ON we.id_artikel = wa.id_artikel
WHERE
	we.id_kunde = $kunde
```
Jetzt sehen wir schnell, dass du vergessen hast due Kunden-IDs in den ON-Teil zu setzen.

```
...
	LEFT JOIN warenausgang AS wa 
		ON we.id_artikel = wa.id_artikel
		AND we.id_kunde = wa.id_kunde
WHERE ...
```


----------



## Zero2000 (6. August 2012)

Hallo

soweit hatte ich meine Abfrage inzwischen auch, naja außer der lesbaren Form .
Ich habe nun

```
SELECT 
    we.id_kunde,
    we.id_artikel,
    we.id_warenart,
    we.datum AS ein_datum,
    SUM(we.anzahl) AS ein_anzahl,
    wa.id_kunde,
    wa.id_artikel,
    wa.id_warenart,
    wa.datum AS aus_datum,
    SUM(wa.anzahl) AS aus_anzahl
FROM 
    wareneingang AS we 
    LEFT JOIN warenausgang AS wa 
        ON we.id_artikel = wa.id_artikel
		AND we.id_kunde = wa.id_kunde
WHERE
    we.id_kunde = $kunde
		AND wa.id_kunde = $kunde
GROUP BY
	we.id_kunde, we.id_artikel, we.id_warenart
```
Aber irgendwie  rechnet er manches doppelt.

Wareneingänge Warenausgänge32.198 (sollten 16.000 und 99 sein also 16.099) es gibt 2 Eingänge27.900 (sollte 13.300  und 350 sein also 13.950) es gibt 2 Ausgänge11.000 (stimmt) es gibt einen Eingang5.000 (stimmt) es gibt einen Ausgang4.000 (stimmt) es gibt 2 Eingänge1.000 (sollte 500 sein) es gibt einen Ausgang

Vielleicht gibt es hier auch noch eine Lösung? Ich könnte mir vorstellen das es an der GROUP BY Klausel hängt weil ich dort ja nur den wareneingang gruppiere.

LG Maik


----------



## Yaslaw (6. August 2012)

*item: *Du hast we.datum und wa.datim im SELECT Teil. Auch wenn sei nicht im GROUP BY aufgelistet sind, gruppiert MySQL danach, da du auf diese Felder keine GROUP_BY-Funktion gesetzt hast

*item: *Aus demselben Grund Gruppiert MySQL ebenfalls nach den wa-Feldern

*item: *Am besten mal das ganze ohne GROUP BY testen. Und dann wenn du ein lauffähiges Query hast, den GROUP BY darüber setzen (also das JOIN-Query als Subquery nehmen)


----------



## Zero2000 (7. August 2012)

Hallo

gibt es denn vielleicht noch eine andere Lösung um einzeilig alle Ausgänge zusammengerechnet den Eingängen zusammengerechnet gegenüber zu stellen?

Mit dem Join werde ich noch bekloppt.

LG
Maik


----------



## Yaslaw (7. August 2012)

Wie willst du die 2 Tabellen vergleichen ohne eine Verbindung (JOIN)?


----------



## Zero2000 (7. August 2012)

Hallo

also so

```
SELECT id_kunde, id_artikel AS ein_artikel, id_warenart AS ein_warenart, datum AS ein_datum, SUM( anzahl ) AS ein_anzahl
FROM wareneingang
WHERE id_kunde =1
GROUP BY id_kunde, id_artikel, id_warenart
UNION SELECT id_kunde, id_artikel AS aus_artikel, id_warenart AS aus_warenart, datum AS aus_datum, SUM( anzahl ) AS aus_anzahl
FROM warenausgang
WHERE id_kunde =1
GROUP BY id_kunde, id_artikel, id_warenart
```
bekomme ich die richtigen Ergebnisse aber eben untereinander.
Warum klappt das dann mit JOIN nicht nebeneinander?

LG Maik

@Yaslaw
Ich weiß schon das JOIN mein Freund ist, aber leiden kann er mich nicht.
Ich bekomme bei allem was ich mache nicht die richtigen Ergebnisse. Sitze nun schon den 3. Tag nur an dieser einen Sache.


----------



## Yaslaw (7. August 2012)

Dein Problem ist, dass du scheinbar keine klaren Schlüssel zum verknüpfen hast.

Kann eine Kombination id_kunde & id_artikel mehr als eine Zeile haben? Wenn ja, was ist der Schlüssel?


----------



## Zero2000 (7. August 2012)

ich zeige Dir einfach meine Tabellen, ich denke schon das ich klare Schlüssel habe.
Tabelle artikel

```
id, id_kunde, id_warenart, artikel
1, 1, 1, Stift
```
Tabelle kunde

```
id, kunde
1, Ich
```
Tabelle warenart

```
id, warenart
1, Schreiben
```
Tabelle wareneingang, warenausgang

```
id, id_kunde, id_artikel, id_warenart, datum, anzahl
1, 1, 1, 1, 2012-08-07, 3000
```
Versuch das ganze auszulesen mit

```
SELECT we.id_kunde, we.id_artikel AS ein_artikel, we.id_warenart AS ein_warenart, we.datum AS ein_datum, SUM( we.anzahl ) AS ein_anzahl, wa.id_kunde, wa.id_artikel, wa.id_warenart, wa.datum AS aus_datum, SUM( wa.anzahl ) AS aus_anzahl
FROM wareneingang AS we
LEFT JOIN warenausgang AS wa ON we.id_artikel = wa.id_artikel
WHERE we.id_kunde =1
GROUP BY we.id_kunde, we.id_artikel, we.id_warenart
```
Nur rechnet er falsch, wahrscheinlich weil  ich dann doch irgendwo einen Fehler habe.

LG Maik


----------



## Yaslaw (7. August 2012)

Du hast wieder die id_kunde bei deiner Verknüpfung vergessen.

Schön, die Tabellen. Aber welches sind die Schlüsselfelder in wareneingang und warenausgang?

Ist id_warenart auch ein Schlüsselfeld? Wenn ja, ab in den JOIN damit


----------



## Zero2000 (7. August 2012)

das Feld id in allen Tabellen ist auto_increment und PRIMARY.


----------



## Yaslaw (7. August 2012)

Also, dann frag ich anderst. Gibt es pro Kombination id_kunde & id_artikel mehrere id_warenart?


----------



## Zero2000 (8. August 2012)

Nein, es gibt pro id_kunde & id_artikel nur eine id_warenart.
Ich versuche gerade herauszufinden worauf Du hinaus willst, liegt es an der Abfrage im ON-Teil das ich dort einfach die Beziehung zwischen den tabellen falsch darstelle****


----------



## Zero2000 (10. August 2012)

Hallo,

nun bin ich schon ein Stück weiter und auch schlauer.
Mein Weg zum Erfolg wird wahrscheinlich kein JOIN sein sondern eine korrelierte Unterabfrage, welche ich mir schon zusammengeschustert habe, aber noch nicht 100%ig funktioniert.

So sieht meine Abfrage nun aus

```
SELECT we.id_kunde, we.id_artikel AS ein_artikel, we.id_warenart AS ein_warenart, we.datum AS ein_datum, wa.id_kunde, wa.id_artikel, wa.id_warenart, wa.datum AS aus_datum,
       (SELECT SUM(we.anzahl) FROM wareneingang we WHERE we.id_kunde = $kunde AND we.id_artikel = wa.id_artikel AND we.id_warenart = wa.id_warenart) ein_anzahl,
       (SELECT SUM(wa.anzahl) FROM warenausgang wa WHERE wa.id_kunde = $kunde AND wa.id_artikel = we.id_artikel AND wa.id_warenart = we.id_warenart) aus_anzahl
FROM wareneingang we, warenausgang wa
WHERE we.id_kunde = $kunde
GROUP BY we.id_kunde, we.id_artikel, we.id_warenart
```
In der Spalte Wareneingang bekomme ich zumindest in der ersten Zeile den richtigen Wert und in der Spalte Warenausgang stimmen alle Werte! ;-)
In der Spalte Wareneingang setzt er in alle Zeilen den Wert aus der ersten Zeile, aber Warum? 

anbei mal ein Bild von der Ausgabe.

Wo könnte denn hier noch der Fehler sein? Die Abfragen sind doch identisch.

Hier mal meine komplette Datei

```
<?php
if(isset($_POST['bk_submit']))
{
$kunde = $_POST['kunde'];

$result = mysql_query("
SELECT we.id_kunde, we.id_artikel AS ein_artikel, we.id_warenart AS ein_warenart, we.datum AS ein_datum, wa.id_kunde, wa.id_artikel, wa.id_warenart, wa.datum AS aus_datum,
       (SELECT SUM(we.anzahl) FROM wareneingang we WHERE we.id_kunde = $kunde AND we.id_artikel = wa.id_artikel AND we.id_warenart = wa.id_warenart) ein_anzahl,
       (SELECT SUM(wa.anzahl) FROM warenausgang wa WHERE wa.id_kunde = $kunde AND wa.id_artikel = we.id_artikel AND wa.id_warenart = we.id_warenart) aus_anzahl
FROM wareneingang we, warenausgang wa
WHERE we.id_kunde = $kunde
GROUP BY we.id_kunde, we.id_artikel, we.id_warenart
")or die (mysql_error());

$arrartikel = array(); 
$arrwarenart = array();
$arrkunde = array();

$query1 = mysql_query("SELECT artikel FROM artikel");
while($row1 = mysql_fetch_array($query1))
{
   $arrartikel[] = $row1['artikel'];
}
$query2 = mysql_query("SELECT warenart FROM warenart");
while($row2 = mysql_fetch_array($query2))
{
   $arrwarenart[] = $row2['warenart'];
}
$query3 = mysql_query("SELECT kunde FROM kunde");
while($row3 = mysql_fetch_array($query3))
{
   $arrkunde[] = $row3['kunde'];
}

$arrartikel = array_values($arrartikel);
$arrartikel = array_combine(range(1, count($arrartikel)), array_values($arrartikel));
$arrwarenart = array_values($arrwarenart);
$arrwarenart = array_combine(range(1, count($arrwarenart)), array_values($arrwarenart));
$arrkunde = array_values($arrkunde);
$arrkunde = array_combine(range(1, count($arrkunde)), array_values($arrkunde));

echo "<h2>Bestandsliste für ".$arrkunde[$kunde]."</h2>";

//Tabellenbeginn
echo "<table border='0' cellspacing='1' cellpadding='2' bgcolor='#000000' width='730'>"; 
echo "<tr bgcolor='#DCE3F4'><td><b>Nr.</b></td><td><b>Bezeichnung</b></td><td><b>Warenart</b></td><td><b>Wareneingänge</b></td><td><b>Warenausgänge</b></td><td align='center'><b>Bestand</b></td><td align='center'><b>Letzter Zugriff<br>Eingang | Ausgang</b></td></tr>";

$nummer = 1;
// Beginn der Schleife
while ($row = mysql_fetch_assoc($result)) { 
	
	$bestand = $row['ein_anzahl'] - $row['aus_anzahl'];
	
    echo '<tr bgcolor="#EDF3F4">'
		.'<td>'.$nummer++.'</td>'
        .'<td>'.$arrartikel[$row['ein_artikel']].'</td>' 
        .'<td>'.$arrwarenart[$row['ein_warenart']].'</td>'
		.'<td>'.number_format($row['ein_anzahl'],0,',','.').'</td>'
		.'<td>'.number_format($row['aus_anzahl'],0,',','.').'</td>'
		.'<td align="right"><strong>'.number_format($bestand,0,',','.').'</strong></td>'
		.'<td align="center">'.date_mysql2german($row['ein_datum']).' | '.date_mysql2german($row['aus_datum']).'</td>' 
        .'</tr>' 
        ."\n";
} 
echo "</table>"; 
mysql_close(); 
}
?>
```


----------

