2009-03-26 5 views
1

ich diese Datenbankstruktur haben:MySQL Query-Hilfe: Gelenke mit Summen und zählt

TBL_A | TBL_B | TBL_C | TBL_D | TBL_E 
-------+---------+---------+---------+---------- 
id  | id_tbla | id_tbla | id_tbla | id 
name | id_user | id_user | id_user | name_tbla 
... | is_bool |   | weight | id_user 

Hier ist, was ich zu erreichen bin versucht:

SELECT 
    a.id, 
    a.name, 
    b.is_bool, 
    count(c.id_user) AS nb_views, 
    sum(d.weight) AS total_weight, 
    count(distinct e.id_user) AS distinct_users, 
FROM TBL_A AS a 
LEFT JOIN (TBL_B AS b) on (b.id_tbla = a.id) 
LEFT JOIN (TBL_C AS c) on (c.id_tbla = a.id) 
LEFT JOIN (TBL_D AS d) on (d.id_tbla = a.id) 
LEFT JOIN (TBL_E AS e) on (e.name_tbla = a.name) 
where a.id = 1 and e.id_user = 1 

Die Abfrage durchgeführt wird, aber die Ergebnisse (nb_views, total_weight, distinct_users) sind falsch. Irgendeine Idee warum?

Antwort

1

Sie versuchen, zu viele Aggregate in einer Abfrage zu berechnen.

Enita non sunt multiplicanda praeter necessitatem

(lateinisch: "Entitäten sind nicht über das Notwendige hinaus multipliziert werden")

Ihre Tabellen B, C, D und E hergestellt werden Cartesian Products gegeneinander. Angenommen, die gegebene Zeile in A übereinstimmt:

  • 3 Reihen in B
  • 6 Reihen in C
  • 4 Reihen in D
  • 1 row in E

Die Gesamtzahl der Zeilen im Ergebnis ist 3 * 6 * 4 * 1 = 72 Zeilen. Also Ihr count(c.id_user) ist 12-mal, was es sein sollte, Ihre sum(d.weight) 18-mal ist, was es sein sollte, usw.

Die einfachste Lösung ist jedes dieser Aggregate in einer separaten Abfrage zu berechnen:

SELECT a.id, a.name, COALESCE(b.is_bool, FALSE) AS is_bool 
FROM TBL_A AS a LEFT JOIN TBL_B AS b ON (b.id_tbla = a.id) 
WHERE a.id = 1; 

SELECT a.id, COUNT(c.id_user) AS nb_views 
FROM TBL_A AS a LEFT JOIN TBL_C AS c ON (c.id_tbla = a.id) 
WHERE a.id = 1; 

SELECT a.id, SUM(d.weight) AS total_weight, 
FROM TBL_A AS a LEFT JOIN TBL_D AS d ON (d.id_tbla = a.id) 
WHERE a.id = 1; 

SELECT a.id, COUNT(DISTINCT e.id_user) AS distinct_users, 
FROM TBL_A AS a LEFT JOIN TBL_E AS e 
    ON (e.name_tbla = a.name AND e.id_user = 1) 
WHERE a.id = 1; 
+0

Perfect! Du hast mir sogar geholfen, die Zahlen zu verstehen, die ich von der Anfrage bekommen habe. Ich werde dann 4 Anfragen machen! So viel für den Versuch, alles auf einmal für ein paar Stunden zu machen ... :) – karlipoppins