2014-04-20 9 views
6

Ich habe drei Tabellen, die ich beitreten. submissions, submissions_votes und users.Erhalten Gesamtanzahl von Zählen, wenn Benutzer gewählt

Ich möchte herausfinden, wie viele insgesamt hilfreichVotes gibt es (das ist eine Summe der Anzahl aller submissions_votes) und ich habe das.

Ich möchte auch eine Zählung (boolean, eher) von 0 oder 1, wenn die user_id von sv.user_id bezieht sich auf die Einreichung wird angezeigt. Die user_id wird an die WHERE Klausel übergeben.

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 

Ich weiß, dass ich eine zusätzliche anschließen müssen (auf sv.user_id = u.id), aber was würde ich wählen? Dann würde ich nach sv.id gruppieren?

Edit:

users Tabelle:

+----------------+------------------------+------+-----+-------------------+-----------------------------+ 
| 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 Tabelle:

+---------------+---------------------+------+-----+---------+----------------+ 
| 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 Tabelle:

+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------+-----+---------+----------------+ 
| 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

bieten Sie Ihre Tabellenstruktur, um Sie weiter zu unterstützen. Wir machen einige Annahmen und wenn das nicht zu Ihrem Strukturcode passt, ist das nicht sinnvoll. – Murtaza

+0

Um die Stimmen jeder Einreichung zu zählen, müssen Sie die Tabelle der Stimmen unbedingt nach Einreichung gruppieren; Aber dadurch wird es bedeutungslos, auf die (die 'user_id' von) * der * Stimme zu verweisen, die mit dieser Einreichung verbunden ist: es könnte sehr viele geben. Daher müssen Sie Ihr Problem besser definieren, was oft am einfachsten mit einem anschaulichen Beispiel für Tabelleninhalte und gewünschte Ergebnisse geschieht. Man könnte vermuten, dass der Boolesche Wert anzeigen soll, ob mindestens eine der Stimmen vom Eigentümer der Vorlage abgegeben wurde, aber das ist überhaupt nicht klar aus Ihrer Frage. – eggyal

+0

@bob_cobb: Die Aussage als sieht für mich falsch aus. Sie fassen alle Upvotes der Einreichungen eines Benutzers zusammen und zeigen dann den Benutzer und einen zufälligen Einreichungsdatensatz an. Das ist sicherlich nicht das, was du willst, oder? –

Antwort

1

Sie überprüfen können, ob die sv.user_id = user_id Eingang CASE und SUM it up (gruppiert nach jeder Vorlage) verwenden. Wenn SUM 1 ist, hat die Eingabe user_id eine Eingabe, sonst nicht. Ihre Eingabe user_id würde also in die CASE-Funktion gehen.

Auch erfordert die COALESCE(SUM(sv.up), 0) eine Gruppierung von welcher auch immer Spalten von submissions und users Tabellen ausgewählt werden.

Die folgende Abfrage basiert auf den Tabellen 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; 

(Wenn mehr Spalten aus der submissions Tabelle ausgewählt werden müssen, dann müssen sie entweder gruppiert oder aggregiert werden)

+0

Ja, das sollte funktionieren ... obwohl breite 'GROUP BY's oder Aggregate oft Crimpperformance haben. –

0

Ich benutze mssql, weiß also nicht genau, ob meine Antwort für mysql funktioniert. In mssql würde die Abfrage in der Frage nicht ohne eine Gruppe funktionieren. Wenn du die Gruppe draußen gelassen hast, solltest du srsv.unterlauf_id in die Gruppe einschließen. Sie haben Unter der Annahme einer Einschränkung, die pro Vorlage und Benutzer nur auf submission_vote gibt es folgendes arbeiten macht sicher:

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

Ohne 'GROUP BY' sind die Ergebnisse von' SUM() 'nicht das, was Sie erwarten ... –

1

Ich glaube nicht, Sie kommen zusätzlich benötigen. Nur ein boolean Ausdruck in der 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' ist eine versteckte/nicht aggregierte Spalte, daher sind die Ergebnisse hier unbestimmt. In dieser Lösung "s. *" Sind auch (obwohl ich vermute, dass die OP beabsichtigt, durch 's.id' zu gruppieren). – eggyal

+0

@eggyal. . . Ich habe die 'Gruppe von 'hinzugefügt, die wahrscheinlich das ursprüngliche Problem des OP behebt. Danke, dass du darauf hingewiesen hast. Und eine Aggregation, um die Anzahl der abgegebenen Stimmen des Einsenders zu zählen. –

+0

Aber die Gruppierung nach diesen Spalten ändert nichts an dem Punkt, der in meinem ersten Kommentar gemacht wurde: 'sv.user_id' ist versteckt und somit sind deine' SubmissionUserMatches' Werte unbestimmt. – eggyal

0

prüfen diese

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

Um die Summe für alle Einreichungen und die Summe für die Anträge nur für der Benutzer (Oder andere benutzerspezifische Aggregationen), können Sie der Tabelle submission_votes zweimal mit einem anderen Alias ​​für die zweite Verbindung zur Tabelle beitreten. Dies ermöglicht eine beliebige Aggregation benutzerspezifischer Submission_Vote-Details.

Dies ist Pseudocode - die GROUP BY s * wird durch die Felder ersetzt werden müssen Sie die Auswahl und Gruppierung von:

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

Ich bin nicht klar, was die boolean, um anzuzeigen, soll aber. Ich nehme an, ob es mindestens eine Stimme von der angegebenen user_id in submission_votes gibt, denn wenn alle Stimmen in submission_votes mit user_id in Beziehung stehen sollen, wäre der Boolesche Wert überflüssig, da man sich die Anzahl ansehen kann.

Ich denke, Unterabfragen sind der Weg zu gehen. Versuchen Sie etwas wie folgt:

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 
Verwandte Themen