2010-05-27 8 views
12

sto avendo 2 tabelle: membri e commenti. Seleziono tutti i membri e quindi aggiungo commenti. Ma nei commenti sto selezionando alcuni SUM di punti, e se l'utente non ha mai commentato, non riesco a ottenere quell'utente nell'elenco ?!MySql che seleziona il valore predefinito se non ci sono risultati?

Così come per selezionare il valore predefinito per somma da 0 se l'utente non ha commentato, o qualche altra soluzione:

SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
      SUM(c.vote_value) AS vote_value, SUM(c.best) AS best, 
      SUM(c.vote_value) + SUM(c.best)*10 AS total 
      FROM members m 
      LEFT JOIN comments c ON m.member_id = c.author_id 
      GROUP BY c.author_id 
      ORDER BY m.member_id DESC 
      LIMIT 0, 20 

EDIT:

cercherò di spiegare .. Quindi ci sono 2 tabelle, membri e commenti. Ho bisogno di un elenco di tutti gli utenti con classifica. I commenti contengono tutti i voti e le migliori risposte.

Quindi, ho bisogno di un elenco di tutti gli utenti, e loro punteggio. tavolo

Membri:

member_id - username - avatar 

Commenti tavolo

comment_id - author_id - vote_value - best (0 OR 1) 

cercato anche di scegliere tra commenti e partecipare I membri, ma stessa cosa di nuovo :(

+0

Potete fornire alcuni dati di esempio con un risultato atteso? Non uso MySQL, quindi forse hanno una sintassi di scelta rapida, ma stai raggruppando su una sola colonna ma hai diverse colonne non aggregate nella tua SELECT –

+0

@Tom H .: MySQL in realtà consente questa sintassi: [GROUP BY e HAVING with Hidden Columns] (http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html). –

+0

Grazie Peter. Sapevo che almeno uno dei principali RDBMS lo permetteva, ma non riuscivo a ricordare quale. Poiché consente raggruppamenti "illogici", tuttavia, potrebbe causare dati "mancanti" perché "Quando si utilizza questa funzione, tutte le righe in ogni gruppo devono avere gli stessi valori per le colonne omesse dalla parte GROUP BY. Il server è gratuito per restituire qualsiasi valore dal gruppo, quindi i risultati sono indeterminati a meno che tutti i valori non siano gli stessi. " c.comment_id potrebbe non essere sempre lo stesso per un dato c.author_id –

risposta

18

Non sono sicuro del motivo per cui si include il comment_id nell'elenco SELECT se si desidera solo utenti e il loro posizionamento. Vuoi solo il loro ranking su quel particolare commento? Ti darò una soluzione per ora che presuppone che si desidera solo un elenco membro a pieno titolo con classifiche:

SELECT 
    M.member_id, 
    M.user_id, 
    M.avatar, 
    COALESCE(SUM(C.vote_value), 0) AS vote_value_sum, 
    COALESCE(SUM(C.best), 0) AS best_sum, 
    COALESCE(SUM(C.vote_value), 0) + SUM(C.best) * 10 AS total_value 
FROM 
    Members M 
LEFT OUTER JOIN Comments C ON 
    C.author_id = M.member_id 
GROUP BY 
    M.member_id 
ORDER BY 
    total_value DESC 
LIMIT 0, 20 

(questo presuppone che vote_value e meglio non sono colonne NULL o che MySQL non terrà conto di quelli in cui il calcolo dei valori SUM - I credete che lo faccia, ma non l'ho provato)

-1

Si potrebbe usare l'istruzione if per convertire NULL in 0

SELECT c.comment_id AS item_id, ... 
    IF(SUM(c.vote_value) is null, 0, SUM(c.vote_value)) as vote_value 
FROM members m 
LEFT JOIN comments c ON ... 
+1

COALESCE fa la stessa cosa, ma è più semplice. SUM (COALESCE (c.vote_value, 0)) – nathan

+1

Questo è un meccanismo goffo per farlo. 'Se (x è NULL, y, x)' non è molto ordinato. –

+0

@nathan: non lo sapevo prima ma solo per usarlo. Grazie (btw, ho dovuto usare COALESCE (SUM (col), 0) perché viceversa ancora restituito nulla –

-1

si potrebbe avere uno sguardo alla istruzione CASE, troppo: http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

Nel tuo caso il risultato sarebbe simile a ...

SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
     (CASE SUM(c.vote_value) WHEN NULL THEN 0 
     ELSE SUM(c.vote_value) END) AS vote_value, SUM(c.best) AS best, 
     (CASE SUM(c.vote_value) + SUM(c.najbolji)*10 WHEN null THEN 0 
     ELSE SUM(c.vote_value) + SUM(c.najbolji)*10 END) AS total 
     FROM members m 
     LEFT JOIN comments c ON m.member_id = c.author_id 
     GROUP BY c.author_id 
     ORDER BY m.member_id DESC 
     LIMIT 0, 20 
+0

Questo è extra-goffi, purtroppo –

18

MySQ L ha un operatore IFNULL che consente di restituire un valore diverso da null se il risultato è nullo.

SELECT c.comment_id AS item_id, m.member_id AS member_id, m.avatar, 
      SUM(IFNULL(c.vote_value, 0)) AS vote_value, SUM(IFNULL(c.best, 0)) AS best, 
      SUM(IFNULL(c.vote_value, 0)) + SUM(IFNULL(c.best, 0))*10 AS total 
      FROM members m 
      LEFT JOIN comments c ON m.member_id = c.author_id 
      GROUP BY c.author_id 
      ORDER BY m.member_id DESC 
      LIMIT 0, 20 

Come altri già menzionati, COALESCE fa qualcosa di simile (e funziona anche su MySQL).

+0

Probabilmente è un po 'meglio di 'COALESCE 'per la circostanza di volere un valore predefinito –

+0

Inoltre non tutti gli utenti nell'elenco: \ – Kenan

+0

Quindi è molto probabile che @nathan sia corretto. Prova a raggruppare su m.member_id invece di c.author_id per vedere se questo aiuta. –

2

Non penso che la SUM sia il problema. Penso che possa essere la vostra

GROUP BY c.author_id 

in cui si esegue il raggruppamento dal lato destro di un join esterno sinistro. Non sono sicuro di quello che succede quando il lato destro non esiste, ma immagino che non sia quello che vuoi veramente. Molto probabilmente dovresti raggruppare per qualcosa nei membri, non per i commenti.

Detto questo, si, si dovrebbe anche usare COALESCE o IFNULL per trasformare valori nulli a 0.

+0

Provato con il raggruppamento m.member_id ma sempre uguale, non tutti gli utenti in elenco. Ho modificato la mia domanda con le strutture della tabella, forse aiuterà a capire meglio. Grazie – Kenan

+0

Prova ad analizzare la query e a ricostruirla per vedere quale parte la rompe. Inizia con "SELECT m.member_" id, SUM (c.vote_value) FROM ... "per assicurarsi che funzioni, quindi aggiungere gli altri SUM e colonne uno alla volta per trovare il problema. – nathan

Problemi correlati