SQL Datenbankabfrage INNER JOIN - COUNT

fixxxxxi

Erfahrenes Mitglied
Hallo,

ich möchte eine Datenbankabfrage machen bei welcher auf zwei Tabellen zugegriffen werden muss. Jedoch komm ich irgendwie damit nicht weiter.

Diese Abfrage funktioniert soweit, nur weiß ich nicht, wie ich nun auch noch ein COUNT() einbauen kann, denn ich möchte das Ergebnis als Zahl ausgegeben haben.


SQL:
SELECT ic1_wars.id, ic1_wars.wlp, ic1_warmember.wid, ic1_warmember.aktion, ic1_warmember.uid 
FROM ic1_wars 
INNER JOIN ic1_warmember ON (ic1_wars.id = ic1_warmember.wid) 
WHERE ic1_warmember.uid=1 
AND ic1_wars.wlp=1 
AND ic1_warmember.aktion=1
GROUP BY ic1_wars.id, ic1_wars.wlp, ic1_warmember.wid, ic1_warmember.aktion, ic1_warmember.uid

Mein Lösungsansatz, bei welchem allerdings einfach nur ein Feld COUNT(*) erstellt wird, wo überall eine 1 drin steht:

SQL:
SELECT COUNT(*), ic1_wars.id, ic1_wars.wlp, ic1_warmember.wid, ic1_warmember.aktion, ic1_warmember.uid 
FROM ic1_wars 
INNER JOIN ic1_warmember ON (ic1_wars.id = ic1_warmember.wid) 
WHERE ic1_warmember.uid=1 
AND ic1_wars.wlp=1 
AND ic1_warmember.aktion=1
GROUP BY ic1_wars.id, ic1_wars.wlp, ic1_warmember.wid, ic1_warmember.aktion, ic1_warmember.uid

Wie lass ich mir die Zahl ausgeben? Thx 4 help!
 
Zuletzt bearbeitet von einem Moderator:
Hi,

das Problem ist, dass Du die ID mit in die Selektion nimmst

Da es pro ID immer einen Record gibt, bekommst Du überall "1" als Count.

Bei einer SQL GROUP BY erzeugt das Group by einen set aus Records, die Du dann mit einem Aggregationsoperator verarbeiten kann.

Beispiel :

Folgende Tabelle BAZ_TABLE sei gegeben :

FOO_ID
1
1
1
2
2
3


Code:
SELECT FOO_ID, COUNT(*) AS ANZ
    FROM BAZ_TABLE
GROUP BY FOO_ID

Das Group By erzeugt intern sowas :

1 -> [row1,row2,row3];
2 -> [row3,row4]
3 -> [row5]

Du kannst nun auf diese rows mit einem aggregationsoperator zugreifen (z.B. COUNT) erzeugt dann :

1 -> 3
2 -> 2
3 -> 1

Hoffe, es hilft ;-)

Grü0e
gore
 
Ah, so gehts mit dem Zitat ;-)

Dein Problem sollte sich so beheben :

SQL:
SELECT COUNT(*),  ic1_wars.wlp, ic1_warmember.aktion, ic1_warmember.uid 
FROM ic1_wars 
INNER JOIN ic1_warmember ON (ic1_wars.id = ic1_warmember.wid) 
WHERE ic1_warmember.uid=1 
AND ic1_wars.wlp=1 
AND ic1_warmember.aktion=1
GROUP BY ic1_wars.wlp,ic1_warmember.aktion, ic1_warmember.uid

Grützi ;-)
 
Zuletzt bearbeitet von einem Moderator:
Was willst du genau Zählen?

Dein Lösungsansatz müsste eigentlich schon Stimmen, obwohl ich das ganze Verschachteln würde

Wenn ich jedoch deine Eingrenzungen sehe, denke ich das du alles eindeutige Zeilen kriegst. Diese Gruppiert über alle Felder ergibt Einer-Gruppen.

SQL:
SELECT count(data.*), data.*
FROM
	(SELECT 
		w.id, 
		w.wlp, 
		wm.wid, 
		wm.aktion, 
		wm.uid
	FROM 
		(SELECT id, wlp FROM ic1_wars WHERE wlp=1) AS w
		INNER JOIN (SELECT wid, aktion, uid FROM ic1_warmember WHERE uid=1 AND aktion=1) AS wm
			ON (w.id = wm.wid)
	) AS data
GROUP BY 
	data.id, 
	data.wlp, 
	data.wid, 
	data.aktion, 
	data.uid
 
Zuletzt bearbeitet von einem Moderator:
Das GROUP BY nicht, dafür das WHERE. Wenn im Endeffekt kleine Datenmengen herauskommen, ist es ev. schneller zuerst die Datenmenge zu reduzieren, dann die Daten zusammenzufügen.

Gerade wenn über etwa alle Felder Gruppiert wird, gitbs eh kein indexbasiertes Gruppieren mehr.
 
Gerade wenn über etwa alle Felder Gruppiert wird, gitbs eh kein indexbasiertes Gruppieren mehr.

Müsste es nicht heissen : Gerade wenn über etwa alle Felder Gruppiert wird, gitbs eh kein brauchbares Ergebnis mehr ?

Welchen Sinn macht es über alle Felder zu gruppieren? Dann kann man das GroupBy auch weglassen.

Ansonsten stimme ich natürlich zu, Subselects sind besser lesbar.

Allerdings würde ein Subselect im InnerJoin dem Optimizer wohl den Rest geben :

Code:
(SELECT id, wlp FROM ic1_wars WHERE wlp=1) AS w
        INNER JOIN (SELECT wid, aktion, uid FROM ic1_warmember WHERE uid=1 AND aktion=1) AS wm
            ON (w.id = wm.wid)

Damit dürfte die Anwendung jeglicher Statistiken für effizientes Joinen / Einschränken unmöglich gemacht werden.

Bei einem

Code:
     SELECT id, wlp FROM ic1_wars AS w
        INNER JOIN warmember  AS wm
               ON w.id = wm.wid
      WHERE uid=1 AND aktion=1
         AND wlp=1

kann der Optimizer zumindestens noch entscheiden, von welcher Richtung er einschränken will. Gibts keinen Index of auf UID und aktion erzwingst Du mit Deiner Abfrage automatisch einen Full-Table-Scan.

Grüße,
gore
 
Zuletzt bearbeitet:
Müsste es nicht heissen : Gerade wenn über etwa alle Felder Gruppiert wird, gitbs eh kein brauchbares Ergebnis mehr ?

Welchen Sinn macht es über alle Felder zu gruppieren? Dann kann man das GroupBy auch weglassen.
Ja, so sollte es heissen.
Richtig, der Group By macht dann kein Sinn....so hat er es aber......

Wie man das SQL mit Unterabfragen aufbauen soll und was der Optimizer daraus macht, können wir beide hier nicht beurteilen. Performance-Verbesserungen sind keine reinen Theorien, man muss sie austesten da viele Faktoren miteinfliessen. Darum gibts auch selten das einzig richtige Query.
 
Wie man das SQL mit Unterabfragen aufbauen soll und was der Optimizer daraus macht, können wir beide hier nicht beurteilen. Performance-Verbesserungen sind keine reinen Theorien, man muss sie austesten da viele Faktoren miteinfliessen. Darum gibts auch selten das einzig richtige Query.

Eben, mit Theorie hat Performancetuning nix zu tun ;-) Eher was mit best practices und gesundem Menschenverstand (3NF, FK-Indexes etc), die größtenteils datenbankübergreifend funktionieren. . Da hier der Einsatz von MySQL aber am hier wahrscheinlichsten ist, ist eine Diskussion über Optimizer mangels Optimizer hier wohl eh müßig ^^

Grüße,
gore
 
Zurück