2014-04-20 3 views
6

Hai tre tavoli con cui mi sto iscrivendo. submissions, submissions_votes e users.Ottieni il conteggio totale oltre al conteggio se l'utente ha votato

Voglio sapere quante offerte utili totali ci sono (che è una somma del conteggio di tutti submissions_votes) e ce l'ho.

voglio anche restituire un conteggio (booleano, piuttosto) di 0 o 1 se l'user_id di sv.user_id riguarda la presentazione visualizzata. Lo user_id viene passato alla clausola WHERE.

SELECT s.*, 
     u.username, 
     u.photo as userPhoto, 
     COALESCE(SUM(sv.up), 0) helpfulVotes 
    FROM 
     submissions s 
    LEFT JOIN submissions_votes sv on s.id = sv.submission_id WHERE u.id = ? 
    INNER JOIN users u 
    ON s.user_id = u.id 

so che ho bisogno di un ulteriore unisco (su sv.user_id = u.id), ma cosa avrei scegliere? Quindi dovrei raggruppare per sv.id?

Edit:

users tavolo:

+----------------+------------------------+------+-----+-------------------+-----------------------------+ 
| Field   | Type     | Null | Key | Default   | Extra      | 
+----------------+------------------------+------+-----+-------------------+-----------------------------+ 
| id    | int(10) unsigned  | NO | PRI | NULL    | auto_increment    | 
| email   | varchar(128)   | NO | MUL | NULL    |        | 
| username  | varchar(23)   | NO |  | NULL    |        | 
| type   | enum('normal','admin') | NO |  | normal   |        | 
| about   | varchar(255)   | NO |  | NULL    |        | 
| photo   | varchar(32)   | NO |  | NULL    |        | 
+----------------+------------------------+------+-----+-------------------+-----------------------------+ 

submissions_votes tavolo:

+---------------+---------------------+------+-----+---------+----------------+ 
| Field   | Type    | Null | Key | Default | Extra   | 
+---------------+---------------------+------+-----+---------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| submission_id | int(10) unsigned | NO | MUL | NULL |    | 
| when   | datetime   | NO |  | NULL |    | 
| user_id  | int(10) unsigned | NO | MUL | NULL |    | 
| up   | tinyint(3) unsigned | NO |  | NULL |    | 
| down   | tinyint(3) unsigned | NO |  | NULL |    | 
+---------------+---------------------+------+-----+---------+----------------+ 

submissions tavolo:

+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+ 
| Field  | Type                                                                    | Null | Key | Default | Extra   | 
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+ 
| id   | int(10) unsigned                                                                 | NO | PRI | NULL | auto_increment | 
| title  | varchar(255)                                                                  | NO | MUL | NULL |    | 
| slug  | varchar(255)                                                                  | NO |  | NULL |    | 
| description | mediumtext                                                                   | NO |  | NULL |    | 
| user_id  | int(11)                                                                    | NO | MUL | NULL |    | 
| created  | datetime                                                                   | NO |  | NULL |    | 
| type  | enum('tip','request')                                                                | NO |  | NULL |    | 
| thumbnail | varchar(64)                                                                   | YES |  | NULL |    | 
| removed  | tinyint(1) unsigned                                                                 | NO |  | 0  |    | 
| keywords | varchar(255)                                                                  | NO |  | NULL |    | 
| ip   | int(10) unsigned                                                                 | NO |  | NULL |    | 
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+ 
+2

fornire la struttura del tavolo, per aiutarvi ulteriormente. Stiamo facendo alcune ipotesi e se ciò non corrisponde al tuo codice di struttura non sarà utile. – Murtaza

+0

Per poter contare i voti di ciascuna submission, è necessario raggruppare necessariamente la tabella dei voti per sottomissione; ma così facendo, diventa priva di senso riferirsi a (il "user_id' di) * il * voto associato a quella sottomissione: ce ne potrebbero essere molti. Quindi è necessario definire meglio il problema, cosa che spesso si fa più facilmente con un esempio illustrativo del contenuto della tabella e dei risultati desiderati. Si potrebbe azzardare un'ipotesi che il booleano dovrebbe indicare se almeno uno dei voti è stato preso dal proprietario della submission, ma ciò non è affatto chiaro dalla sua domanda. – eggyal

+0

@bob_cobb: l'affermazione mi sembra sbagliata. Sommerai tutti gli upvotes degli invii di un utente, quindi visualizzerai l'utente e un record di invio casuale con esso. Questo non è certamente quello che vuoi, giusto? –

risposta

1

È possibile controllare se il sv.user_id = ingresso user_id utilizzando CASE e SUM in su (diviso per ogni presentazione). Se SUM è 1, l'input user_id ha una sottomissione, altrimenti no. Quindi, il tuo input user_id entrerebbe nella funzione CASE.

Inoltre, il COALESCE(SUM(sv.up), 0) richiede un raggruppamento per qualunque siano selezionate colonne di submissions e users tabelle.

Quella che segue è la query basata sulle tabelle nello SQL Fiddle here.

SELECT 
    s.id as submission_id, 
    s.title as submission_title, 
    MAX(u.email) as submission_user_email, 
    COALESCE(SUM(sv.up), 0) helpfulVotes, 
    SUM(CASE sv.user_id 
     WHEN ? THEN 1 
     ELSE 0 
     END) User_Submission 
FROM 
    submissions s 
LEFT JOIN submissions_votes sv on s.id = sv.submission_id 
INNER JOIN USERS u 
ON s.user_id = u.id 
GROUP BY s.id, s.title; 

(Se più colonne dalla tabella submissions devono essere selezionati, allora devono essere o raggruppati o aggregati)

+0

Sì, questo dovrebbe funzionare ... anche se larghe 'GROUP BY' o aggregati spesso compromettono le prestazioni. –

0

Uso mssql quindi non so se la mia risposta funzionerà per mysql. In mssql la query nella domanda non funzionerebbe senza un gruppo di. se hai lasciato il gruppo fuori, dovresti includere srsv.submission_id nel gruppo per. si Supponendo che hanno un vincolo che rende sicuro c'è solo il submission_vote per la presentazione e l'utente il seguente dovrebbe funzionare:

SELECT s.*, 
    u.username, 
    u.photo as userPhoto, 
    COALESCE(SUM(sv.up), 0) helpfulVotes 
    case when srsv.submission_id is null then 1 else 0 end SelfRelatedVote 
FROM 
    submissions s 
LEFT JOIN submissions_votes sv on s.id = sv.submission_id 
Left JOIN submissions_votes srsv on s.id = srsv.submission_id and s.user_id = srsv.user_id 
INNER JOIN users u 
ON s.user_id = u.id 
+0

Senza un 'GROUP BY', il risultato di' SUM() 'non sarà quello che ti aspetti ... –

1

non credo che avete bisogno di un ulteriore join. Solo un'espressione booleana nella select:

SELECT s.*, 
     u.username, 
     u.photo as userPhoto, 
     COALESCE(SUM(sv.up), 0) helpfulVotes, 
     SUM(sv.user_id = u.id) as SubmissionUserMatches 
FROM submissions s LEFT JOIN 
    submissions_votes sv 
    on s.id = sv.submission_id INNER JOIN 
    users u 
    ON s.user_id = u.id 
GROUP BY s.id, u.username, u.photo; 
+0

' sv.user_id' è una colonna nascosta/non aggregata, quindi i risultati qui saranno indeterminati. Del resto, anche in questa soluzione sono presenti 's. *' (Anche se sospetto che l'OP intenda raggruppare per 's.id'). – eggyal

+0

@eggyal. . . Ho aggiunto il 'group by' che probabilmente corregge il problema originale dell'OP. Grazie per averlo indicato. E una aggregazione per contare il numero di voti fatti dal mittente per la presentazione. –

+0

Tuttavia il raggruppamento da quelle colonne non cambia il punto fatto nel mio primo commento: 'sv.user_id' è nascosto e quindi i valori di' SubmissionUserMatches' saranno indeterminati. – eggyal

0

Scegli questa

SELECT s.*, 
    u.username, 
    COALESCE(SUM(sv.up), 0) helpfulVotes, 
    IF (srsv.submission_id is null, 1, 0) 
FROM 
    submissions s 
LEFT JOIN submissions_votes sv on s.id = sv.submission_id 
LEFT JOIN submissions_votes srsv on s.id = srsv.submission_id and s.user_id = {USER_ID} 
INNER JOIN users u ON s.user_id = u.id 
0

Per ottenere il totale per tutte le comunicazioni, e il totale di presentazione di solo per l'utente (o altre aggregazioni specifiche dell'utente), è possibile unirsi alla tabella submission_votes due volte, con un alias diverso per la seconda connessione alla tabella. Ciò consentirà qualsiasi aggregazione sui dettagli di Submission_Vote specifici dell'utente.

Questo è il codice pseudo - GROUP BY s * dovrà essere sostituito con i campi si selezionano e il raggruppamento di:

SELECT 
    s.* 
    ,u.username 
    ,u.photo      AS userPhoto 
    ,COALESCE(SUM(sv.up), 0)  AS helpfulVotes 
    ,COALESCE(SUM(sv_user.up), 0) AS helpfulVotes_user 
FROM 
    submissions s 

    LEFT JOIN submissions_votes sv 
    on s.id = sv.submission_id 

    LEFT JOIN submissions_votes sv_user 
    on s.id = sv_user.submission_id 

    INNER JOIN users u 
    ON s.user_id = u.id 

WHERE 
    sv_user.user_id = @User_id 
GROUP BY 
    s.* 
    ,u.username 
    ,u.photo   
0

Non ho chiaro che cosa si suppone che il booleano per indicare ma. Suppongo sia che ci sia almeno 1 voto da user_id fornito in submission_votes perché se tutti i voti in submission_votes dovessero essere correlati a user_id, allora il booleano sarebbe ridondante in quanto si potrebbe solo guardare il conteggio.

Penso che le subquery siano la strada da percorrere. Prova qualcosa del genere:

SELECT s.*, 
     u.username, 
     u.photo as userPhoto, 
     COALESCE(
     (
     SELECT SUM(sv.up) FROM 
     submission_votes sv 
     WHERE sv.submission_id = s.id 
    ), 0) helpfulVotes, 
     (CASE 
     WHEN EXISTS (SELECT 1 
      FROM submission_votes 
      WHERE sv.submission_id = s.id 
      AND sv.user_id = ?) 
     THEN 1 
     ELSE 0 
     END) userSubmissionVoteExists 
    FROM 
    submissions s 
    INNER JOIN users u ON s.user_id = u.id 
Problemi correlati