2017-04-01 4 views
1

Ich habe ein System, mit dem Benutzer Zeitpläne von Videos zu sehen erstellen können. Die folgende MySQL-Datenbank zieht aktive Zeitpläne und Informationen über die Anzahl der Videos im Zeitplan, die Anzahl bereits angesehener und die Anzahl, die heute angesehen werden soll. Dies geschieht über mehrere Joins zu derselben Tabelle, die Verknüpfungen von Zeitplänen zu Videos verfolgt.Warum brauche ich COUNT (DISTINCT ...) in diesem MySQL?

SELECT 
    schedules.*, 
    COUNT(DISTINCT sv1.vid_id) AS total_vids, #<-- the problem 
    GROUP_CONCAT(DISTINCT sv1.context_node_id) AS topics, 
    COUNT(sv2.vid_id) AS vids_watched, 
    COUNT(sv3.vid_id) AS today 
FROM schedules 
JOIN schedule_vids sv1 ON schedules.id = sv1.schedule_id 
LEFT JOIN schedule_vids sv2 ON schedules.id = sv2.schedule_id && sv2.watched IS NOT NULL 
LEFT JOIN schedule_vids sv3 ON schedules.id = sv3.schedule_id && sv3.date = CURDATE() 
WHERE user_id = ? && schedules.id = ? 
GROUP BY schedules.id 
ORDER BY created DESC 

Das Problem: die weit über die wahre Zahl wenn ich mir eine Nummer nicht COUNT (DISTINCT sv1.vid_id) (das heißt nur COUNT(sv1.vid_id)) verwenden zu bekommen. Ich habe das in der DB verifiziert. Weiß jemand, wo ich falsch liege?

Interessanterweise verschwindet das Problem, wenn ich die Verknüpfung zu SV3 (und den entsprechenden Teil der SELECT-Anweisung, natürlich) entfernen.

[UPDATE]

Hier ist die Tabellenstruktur für die beiden beteiligten Tabellen:

CREATE TABLE `schedules` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
`name` varchar(50) NOT NULL, 
`user_id` varchar(11) NOT NULL, 
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
`start` date NOT NULL, 
`end` date NOT NULL, 
`inc_weekends` enum('y') DEFAULT NULL, 
`type` enum('ls','c') NOT NULL DEFAULT 'ls' COMMENT 'ls = learning schedule; c = course', 
`subj_id` varchar(30) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=MyISAM AUTO_INCREMENT=51 DEFAULT CHARSET=latin1 

und

CREATE TABLE `schedule_vids` (
`schedule_id` int(11) NOT NULL, 
`vid_id` varchar(11) NOT NULL, 
`context_node_id` varchar(11) NOT NULL, 
`date` date NOT NULL, 
`watched` date DEFAULT NULL, 
PRIMARY KEY (`schedule_id`,`vid_id`,`context_node_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

Beispielausgabe:

id    50 
name   some-schedule 
user_id   yd8i0i63bd8 
created   2017-04-01 11:58:22 
start   2017-04-01 
end    2017-04-03 
inc_weekends y 
type   ls 
total_vids  91 
topics   maths 
vids_watched 0 
today   91 
+1

Beispieldaten und gewünschte Ergebnisse würden anderen helfen, das Problem zu verstehen. –

+0

Aktualisierung ....... – Utkanos

Antwort

2

Aller Wahrscheinlichkeit nach, du nicht brauchen die distinct. Das Problem sind deine Joins. Verwenden Sie stattdessen bedingte Aggregation:

Wenn Sie Ihre Abfrage ohne Aggregation ausführen, werden Sie sehen, was passiert. Du bekommst ein kartesisches Produkt von Videos, weshalb die Zählimpulse aus sind.

+0

Danke für Ihre Hilfe. Ich bekomme jedoch "Unbekannte Spalte 'sv3.date' in 'Feldliste'" - kann nicht sehen, wo Sie 'sv3' definieren, wie ich es tat, oder sollte ich dieses Bit füllen? – Utkanos

+0

Und was ist der Grund für 'SUM()' anstatt 'COUNT()'? – Utkanos

+1

Ich denke, die SV3 sollte nur SV sein, es wurde versehentlich zurückgelassen. –