SQL Abfrage über mehrere Tabellen und Count

djrick

Registered User
Hallo,

Ich brüte schon seit ein paar Tagen über eine SQL Abfrage die ich nicht richtig hinbekomme.

Hier mal meine Datenbankstruktur:

Tabellen:
Benutzer
Benutzer_Details
Artikel

In der Tabelle benutzer stehen alle Benutzer mit Namen und natürlich einer eindeutigen UserID.
In der Tabelle benutzer_details stehen noch details zu dem Benutzer (PLZ, Telefon etc.) auch hier habe ich wieder eine userid die gleich der userid aus benutzer ist.
In der Tabelle: Artikel stehen artikel die der Benutzer hat, das kann 0, 1 oder mehrere sein. Jeder Artikel hat eine Artikelbezeichnung und natürlich eine Spalte wo "userid" drin steht. Sprich: Pro user der einen Artikel hat wird eine Reihe angelegt.

Jetzt möchte ich eine Abfrage die mir jeden Benutzer (einmal) auflistet der einen oder mehr Artikel hat.
Ich krieg es irgendwie nicht hin...umgangssrachlich müsste das irgendwie so lauten:

SELECT Benutzer.*, Benutzer_Details, Artikel.* FROM Benutzer, Benutzer_Details, Artikel WHERE benutzer.userID = benutzer_details.userID, benutzer_userID = Artikel.userID AND Count(Artikel) > 0

Ich habe es schon mit mehreren verschachtelten Left Joins probiert, aber das Problem bei mehreren Artikeln krieg ich nicht gelößt, sagen wir ein Benutzer hat 3 Artikel, dann soll er ja nur EINMAL in der Liste stehen, aber ich kriegs nur hin, dass er den Benutzer dann drei mal hinschreibt.
 
SELECT DISTINCT(Benutzer.userID)
JOIN benutzer_details ON benutzer_details.userID = benutzer.userID,
JOIN artikel ON benutzer.userID = artikel.userID
 
Dir fehlt eine Gruppierung der selektierten Spalten und eine Summe über die Anzahl der Artikel:
Code:
select b.userID, b.name, d.plz, d.ort, sum(a.Artikel) as artikelSum
from Benutzer b
inner join Benutzer_Details d on (d.userID = b.userID)
inner join Artikel a (a.userID = b.userID and a.Artikel > 0)
group by b.userID, b.name, d.plz, d.ort

Gruppiert werden gleiche Einträge weshalb Du auf Details zum Artikel verzichten mußt.
 
Ok jetzt noch die Premiumstufe:

Ich habe nicht nur:
Benutzer
Benutzer_details
Artikel

sondern:
Benutzer
Benutzer_details
Artikel_1
Artikel_2
Artikel_3

Die Anzahl der Artikel ist fest..also 3.
Jetzt möchte ich das ganze so, dass er mir alle Benutzer listet die mindestens einen Artikel haben.

Also es kann sein dass ein Kunde nur Artikel_2 hat oder Artikel_1 und 3...
Also Ziel ist es: Ich hab eine Userdatenbank und ich will nur die Kunden haben, die mindestens einen Artikel gekauft haben.
 
Also das liefert mir nicht das richtige ergebnis:
Code:
SELECT 
  b.userID,
  d.userLastName
FROM
  users b
  INNER JOIN user_details d ON (d.userID = b.userID)
  RIGHT OUTER JOIN artikel1 a1 ON (a1.userID = b.userID)
  RIGHT OUTER JOIN artikel2 a2 ON (a2.userID = b.userID)
GROUP BY
  b.userID
Meine Logik sagt mir das ich das ganze irgendwie ODER verknüpfen muss, aber keine Ahnung wie :confused:
 
Du kannst nur Tabellen JOINEN:

SELECT b.userID, d.userLastName FROM users b JOIN user_details d ON (d.userID = b.userID) JOIN artikel a ON (a.userID = b.userID)
 
Tja das funktioniert mit einem Artikel ja auch alles ganz wunderbar.

Aber wie gesagt, ich hab drei Tabellen (je Tabelle = ein Artikel) und da muss ich das noch irgendwie verschachteln oder mit or verknüpfen oder keine Ahnung :(

Das funktioniert nicht:
Code:
SELECT
	b.userID,
	d.userLastName
FROM
	users b
	JOIN
		user_details d ON (d.userID = b.userID)
	JOIN
		artikel1 a1 ON (a1.userID = b.userID)
	JOIN
		artikel2 a1 ON (a2.userID = b.userID)
 
Warum hast du überhaupt eine solch verkorkste Datenbankstruktur?
Du hast jetzt 3 Produkte? Jedes in einer Tabelle also nur ein Datensatz pro Tabelle? :eek:
 
Ich habe 3 Produkte...jedes Produkt hat seine eigene Tabelle in der gespeichert wird, wer dieses Produkt hat, das macht in diesem Zusammenhang schon sehr gut Sinn...

Die Kundenliste funktioniert auch schon, bloss SEHR SEHR langsam da es von meinem Vorgänger sehr schlecht programmiert wurde...hier mal das PHP Script was ich versuche zu verbessern:
PHP:
$custumers_query = $db->dbQuery("SELECT `users`.`userID`, `user_details`.`userFirstName`, `user_details`.`userLastName`, `user_details`.`userPLZ`, `user_details`.`userPlace` 
  									FROM `users`
  									LEFT JOIN `user_details` ON (`user_details`.`userID` = `users`.`userID`)");
  $tmp_customers = array();
  while($result = $db->fetchobject($custumers_query))
  {
    $anzahl = 0;
    $query_sc = $db->dbQuery("SELECT count(`bestelldatum`) as `bestelldatum` FROM `artikel1` WHERE `status` > 0 AND `userID`=".$result->userID);
    if($query_sc && $db->num_rows($query_sc)==1) $anzahl += $db->fetchobject($query_sc)->bestelldatum;
    $query_ts = $db->dbQuery("SELECT count(`bestelldatum`) as `bestelldatum` FROM `artikel2` WHERE `status` > 0 AND `userID`=".$result->userID);
    if($query_ts && $db->num_rows($query_ts)==1) $anzahl += $db->fetchobject($query_ts)->bestelldatum;
    $query_ts = $db->dbQuery("SELECT count(`bestelldatum`) as `bestelldatum` FROM `artikel3` WHERE `status` > 0 AND `userID`=".$result->userID);
    if($query_ts && $db->num_rows($query_ts)==1) $anzahl += $db->fetchobject($query_ts)->bestelldatum;
    if($anzahl>0) $tmp_customers[] = array($result->userID, $anzahl, $result->userFirstName, $result->userLastName, $result->userPLZ, $result->userPlace);
  }

Durch die While und die 3 SELECT Anweisungen wird es bei einer Datenbank mit jeweils mehr als 10 000 Einträgen pro Tabelle natürlich etwas langsamer...Also möchte ich jetzt die While rausschmeissen.

EDIT:
In einer Tabelle: artikel1 steht zb:

userID, bestelldatum, status, ...

EDIT2:
Wie man sieht versuche ich am Ende ein Array zu erhalten was alle Kunden enthält die mehr als 0 Artikel gekauft haben.
 
Last edited by a moderator:
Also ich habe jetzt alle möglichen Kombinationen von RIGHT, LEFT, INNER Joins durch ich versteh es einfach nicht :(

Nach meiner Logik sollte das mir eine Liste ALLER User liefern mit 3 Spalte wo jeweils die Anzahl der gekauften Artikel drin steht, die Anzahl stimmt aber nicht, denn wenn die erste Spalte zB den Count 4 hat, hat spalte 2 auch automatisch den gleichen Count...und diese Anfrage dauert schon ewig....

Code:
SELECT DISTINCT u.userID, COUNT(artikel2.userID) as art2, COUNT(artikel1.userID) as art1, COUNT(artikel3.userID) as art3
FROM
	popstream_users u
LEFT OUTER JOIN
        customer_artikel1 artikel1 on (artikel1.status = 1 AND u.userID = artikel1.userID)
LEFT OUTER JOIN
        customer_artikel2 artikel2 on (artikel2.status = 1 AND u.userID = artikel2.userID)
LEFT OUTER JOIN
        customer_artikel3 artikel3 on (artikel3.status = 1 AND u.userID = artikel3.userID)
GROUP BY u.userID
 
Ja, bei left/right joins fängt es bei mir auch an sich im Kopf zu drehen, allerdings ist Dein Datenbankschema offensichtlich auch nicht optimal. :mad:

Wenn Du MySQL verwendest, hast Du es vielleich am einfachsten indem Du einen View definierst, der die Tabellen ArtikelX zusammenfasst und Du über diesen View die Auswertung durchführst.

Code:
create view artikelAll 
as
select userId, artikelId, bestelldatum, status, 'artikel1' as artikelTyp from artikel1 where status = 1
union select userId, artikelId, bestelldatum, status, 'artikel2' as artikelTyp from artikel2 where status = 1
union select userId, artikelId, bestelldatum, status, 'artikel3' as artikelTyp from artikel3 where status = 1
 
Wunderbar, das mit der View funktioniert genau so wie ich es haben möchte. Dankeschön.

Ich finde die Struktur schon passend.

Sagen wir ich habe nicht 3 Artikel sondern 3 arten von Servern. Dann finde ich macht so eine Struktur schon Sinn.
 
Back
Top