Frage

Oft müssen Sie jedes Element eine Liste der Datenbankelemente und bestimmten aggregierten Zahlen zeigen. Zum Beispiel, wenn Sie den Titeltext auf Stack-Überlauf eingeben, wird die Verwandte Fragen Liste. Die Liste zeigt den Titel der entsprechenden Einträge und die einzelne aggregierten Anzahl der Anzahl der Antworten für jeden Titel.

Ich habe ein ähnliches Problem, sondern benötigen mehrere Aggregate. Ich möchte eine Liste der Elemente in einem 3 Formaten angezeigt werden, je nach Benutzeroptionen:

  • My Name des Elements (15 insgesamt, 13 von mir gehört)
  • My Name des Elements (15 insgesamt)
  • Name meines Artikels (13 von mir gehört)

Meine Datenbank ist:

  • Elemente : itemId, itemName, ownerId
  • Kategorien : catId, catName
  • Karte : mapId, itemId, catId

Die Abfrage unten bekommt: Kategorienamen, Anzahl der Artikel-IDs pro Kategorie

SELECT
  categories.catName,
  COUNT(map.itemId) AS item_count
FROM categories
LEFT JOIN map
  ON categories.catId = map.catId
GROUP BY categories.catName

Diese erhält man: Kategorienamen, Anzahl der Artikel-IDs pro Kategorie für diese OWNER_ID nur

SELECT categories.catName, 
COUNT(map.itemId) AS owner_item_count
FROM categories
LEFT JOIN map
  ON categories.catId = map.catId
LEFT JOIN items
  ON items.itemId = map.itemId
WHERE owner = @ownerId
GROUP BY categories.catId

Aber wie ich sie in einer einzigen Abfrage zur gleichen Zeit bekommen? D.h .: Kategorienamen, Anzahl der Artikel-IDs pro Kategorie, Anzahl der Artikel-IDs pro Kategorie für diese OWNER_ID nur

Bonus. Wie kann ich abrufen optional nur dort, wo catID zählen! = 0 für alle diese? Bei dem Versuch, "WHERE ITEM_COUNT <> 0" erhalte ich:

MySQL said: Documentation
#1054 - Unknown column 'rid_count' in 'where clause' 
War es hilfreich?

Lösung

Hier ist ein Trick: eine SUM() von Werten berechnen, die dafür bekannt sind, entweder 1 oder 0 entspricht einer COUNT() der Zeilen, in denen der Wert 1 ist und Sie wissen, dass ein boolean Vergleich gibt 1 oder 0 (oder NULL) .

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  LEFT JOIN map m USING (catid)
  LEFT JOIN items i USING (itemid)
GROUP BY c.catid;

Wie für die Bonus-Frage, könnten Sie einfach tun eine innere Verknüpfung statt einer äußeren Verknüpfung, die nur Kategorien bedeuten würde, mit mindestens einer Reihe in map zurückgegeben werden würde.

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  INNER JOIN map m USING (catid)
  INNER JOIN items i USING (itemid)
GROUP BY c.catid;

Hier ist eine andere Lösung, die nicht so effizient ist, aber ich werde zeigen, es zu erklären, warum Sie die Fehlermeldung anzeigt:

SELECT c.catname, COUNT(m.catid) AS item_count,
  SUM(i.ownerid = @ownerid) AS owner_item_count
FROM categories c
  LEFT JOIN map m USING (catid)
  LEFT JOIN items i USING (itemid)
GROUP BY c.catid
HAVING item_count > 0;

Sie können nicht Spalte Aliase in der WHERE Klausel, weil Ausdrücke in der WHERE Klausel verwenden, bevor die Ausdrücke in der Auswahlliste ausgewertet werden. Mit anderen Worten, assoziierten die Werte mit Select-Liste Ausdrücke noch nicht verfügbar ist.

Sie können Spaltenaliasnamen in den GROUP BY, HAVING und ORDER BY Klauseln verwenden. Diese Klauseln werden ausgeführt, nachdem alle Ausdrücke in der Auswahlliste ausgewertet wurden.

Andere Tipps

Sie können eine CASE-Anweisung in Ihrem SUM schleichen ():

SELECT categories.catName, 
    COUNT(map.itemId) AS item_count,
    SUM(CASE WHEN owner= @ownerid THEN 1 ELSE 0 END) AS owner_item_count
FROM categories
LEFT JOIN map  ON categories.catId = map.catId
LEFT JOIN items  ON items.itemId = map.itemId
GROUP BY categories.catId
HAVING COUNT(map.itemId) > 0
SELECT categories.catName, 
  COUNT(map.itemId) AS item_count,
  COUNT(items.itemId) AS owner_item_count
FROM categories
INNER JOIN map
  ON categories.catId = map.catId
LEFT JOIN items
  ON items.itemId = map.itemId
  AND items.owner = @ownerId
GROUP BY categories.catId

Beachten Sie, dass Sie eine HAVING Klausel auf owner_item_count verwenden könnte, aber die innere Verknüpfung kümmert sich um ITEM_COUNT für Sie.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top