2016-06-23 5 views
1

Ich habe ein Ticketing-System, mit dem ich versuche, einen Bericht zu erstellen. Ich versuche, die Anzahl der Tickets pro Benutzer zu erreichen. Mit dieser ersten Abfrage:MySQL zählt mit der Gruppe, weil das Ergebnis nicht korrekt ist

SELECT * FROM (
SELECT TicketID, UserID, EventDateTime 
FROM dcscontact.ticketevents 
WHERE EventDateTime BETWEEN '2016-06-22' AND '2016-06-23' 
ORDER BY EventDateTime DESC) x 
WHERE UserID=80 
GROUP BY TicketID; 

ich in der Lage bin die Tickets für einen bestimmten Benutzer berührt aufzulisten, und sie manuell zählen:

TicketID UserID EventDateTime 
99168  80  6/22/2016 13:21 
99193  80  6/22/2016 7:42 
99213  80  6/22/2016 13:02 
99214  80  6/22/2016 6:30 
99221  80  6/22/2016 6:57 
99224  80  6/22/2016 7:48 
99226  80  6/22/2016 6:27 
99228  80  6/22/2016 8:49 
99229  80  6/22/2016 8:53 
99232  80  6/22/2016 9:18 
99237  80  6/22/2016 13:08 

Aber wenn ich versuche, die WHERE UserID = Anweisung fallen und versuchen, es als eine Unterabfrage wie so zu verwenden:

SELECT UserID, COUNT(*) as count FROM (
    SELECT * FROM (
    SELECT TicketID, UserID, EventDateTime 
    FROM dcscontact.ticketevents 
    WHERE EventDateTime BETWEEN '2016-06-22' AND '2016-06-23' 
    ORDER BY EventDateTime DESC) x 
    GROUP BY TicketID) y 
GROUP BY UserID; 

ich falsche Zählungen erhalten:

UserID count 
9  2 
28  1 
31  1 
42  1 
80  5 
95  1 
99  6 
108  4 
116  12 
117  26 
123  24 

Wie Sie sehen können, sollte die Anzahl der Benutzer-ID 80 11. Die meisten anderen Ergebnisse sind ebenfalls falsch, sie scheinen alle niedrigere Zahlen zu sein, als ich erwartet habe.

Mache ich etwas falsch mit der GROUP BY/COUNT, wenn Sie es für eine Unterabfrage verwenden? Wie kann ich meine Abfrage ändern, um die gewünschten Ergebnisse zu erhalten?

+0

Sie müssen nicht wirklich die gleichen Ergebnisse erneut auswählen, mit denen Sie nur eine Gruppe erstellen mussten. – Dresden

+0

Wenn mehrere Benutzer dieselbe ticketid "berührten", löschte die Gruppe Ihrer inneren Abfrage diese Tatsache effektiv; Die Werte der nicht aggregierten, nicht gruppierten Felder werden zufällig (_effektiv_) aus den Zeilen ausgewählt, die für gruppierte Felder denselben Wert hatten. – Uueerdo

Antwort

3

Wollen Sie nur eine Aggregation?

SELECT UserID, COUNT(*) 
FROM dcscontact.ticketevents 
WHERE EventDateTime BETWEEN '2016-06-22' AND '2016-06-23' 
GROUP BY UserID; 

Wenn das gleiche Ticket in den Daten mehr als einmal für einen bestimmten Benutzer angezeigt werden kann, dann ist COUNT(DISTINCT) geeignetere:

SELECT UserID, COUNT(DISTINCT TicketID) 
FROM dcscontact.ticketevents 
WHERE EventDateTime BETWEEN '2016-06-22' AND '2016-06-23' 
GROUP BY UserID; 
+0

Ah, mir war 'COUNT (DISTINCT)' nicht bewusst, genau das brauchte ich. –

0

Anzahl der Karten pro Benutzer berührt zu erhalten, lassen Sie uns mit einer richtigen Abfrage starten für genau das:

SELECT count(*) as N, UserID 
FROM dcscontact.ticketevents 
WHERE EventDateTime BETWEEN '2016-06-22' AND '2016-06-23' 
GROUP BY UserID; 

A GROUP BY Klausel sollten immer alle nicht-aggre Tor Spalten erwähnt in der SELECT Klausel. Es macht keinen Sinn nach "Ticket-ID und Anzahl der Tickets (pro Benutzer)" zu fragen!

Auch der SQL-Standard sagt ORDER BY kann nicht für Unterabfragen gelten. Am besten denken Sie an ORDER BY als eine Bequemlichkeit zum Anzeigen der Ausgabe, nicht als Informationen in der Abfrage verwendet werden.

Sie möchten auch etwas über die TicketID und EventDateTime wissen. Sie können nicht nach der "ID der Anzahl der Tickets" fragen, aber Sie können das erste und das letzte Ticket erhalten. Gleich für Zeit:

SELECT count(*) as N 
     , min(TicketID) as T1 
     , max(TicketID) as Tn 
     , min(EventDateTime) as E1 
     , max(EventDateTime) as En 
    , UserID 
FROM dcscontact.ticketevents 
WHERE EventDateTime BETWEEN '2016-06-22' AND '2016-06-23' 
GROUP BY UserID; 

Beachten Sie, dass die früheste Zeit möglicherweise nicht die Zeit der kleinsten TicketID ist. Um alles über das erste Ticket für jeden Benutzer plus die Anzahl zu erhalten, schließen Sie sich den beiden Informationsquellen an:

select N.N, T.* 
from dcscontact.ticketevents as T 
join (
    SELECT count(*) as N, min(TicketID) as T1, UserID 
    FROM dcscontact.ticketevents 
    WHERE EventDateTime BETWEEN '2016-06-22' AND '2016-06-23' 
    GROUP BY UserID; 
) as N 
on T.UserID = N.UserID 
and T.TicketID = N.TicketID 
-- and maybe others, according to the key 
order by EventDateTime DESC 
Verwandte Themen