Domanda

Spesso è necessario mostrare un elenco di elementi del database e determinati numeri aggregati su ciascun elemento. Ad esempio, quando si digita il testo del titolo su Stack Overflow, viene visualizzato l'elenco Domande correlate. L'elenco mostra i titoli delle voci correlate e il singolo numero aggregato di quantità di risposte per ciascun titolo.

Ho un problema simile ma ho bisogno di più aggregati. Vorrei visualizzare un elenco di elementi in uno dei 3 formati a seconda delle opzioni dell'utente:

  • Nome del mio articolo (15 in totale, 13 di proprietà di me)
  • Nome del mio articolo (15 in totale)
  • Nome del mio articolo (13 di proprietà di me)

Il mio database è:

  • articoli : itemId, itemName, ownerId
  • categorie : catId, catName
  • mappa : mapId, itemId, catId

La query seguente ottiene: nome della categoria, conteggio degli ID oggetto per categoria

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

Questo ottiene: nome categoria, numero di ID oggetto per categoria solo per questo ID_utente

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

Ma come posso ottenerli contemporaneamente in una singola query? Ad esempio: nome della categoria, conteggio degli ID degli articoli per categoria, conteggio degli ID degli articoli per categoria solo per questo ID_utente

Bonus. Come posso facoltativamente recuperare solo dove catId conta! = 0 per uno di questi? Nel provare & Quot; WHERE item_count & Lt; & Gt; 0 quot &; Ottengo:

MySQL said: Documentation
#1054 - Unknown column 'rid_count' in 'where clause' 
È stato utile?

Soluzione

Ecco un trucco: calcolare un SUM() di valori che sono noti per essere 1 o 0 equivale a COUNT() delle righe in cui il valore è 1. E sai che un confronto booleano restituisce 1 o 0 (o 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;

Per quanto riguarda la domanda bonus, potresti semplicemente fare un join interno anziché un join esterno, il che significherebbe che verranno restituite solo le categorie con almeno una riga in map.

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;

Ecco un'altra soluzione, che non è così efficiente ma la mostrerò per spiegare perché hai ricevuto l'errore:

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;

Non è possibile utilizzare gli alias di colonna nella clausola WHERE, poiché le espressioni nella clausola GROUP BY vengono valutate prima delle espressioni nell'elenco di selezione. In altre parole, i valori associati alle espressioni di elenco di selezione non sono ancora disponibili.

È possibile utilizzare gli alias di colonna nelle clausole HAVING, ORDER BY e <=>. Queste clausole vengono eseguite dopo che tutte le espressioni nell'elenco di selezione sono state valutate.

Altri suggerimenti

Puoi inserire un'istruzione CASE all'interno di SUM ():

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

Nota che puoi utilizzare una HAVING clausola su owner_item_count, ma il join interno si occupa di item_count per te.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top