2017-04-01 30 views
1

我有一個系統,允許用戶創建視頻的時間表觀看。以下MySQL會提取活動計劃以及計劃中的視頻數量,已觀看的數量以及今天要觀看的數量。它通過多個連接到跟蹤時間表到視頻關聯的同一個表執行此操作。爲什麼在這個MySQL中需要COUNT(DISTINCT ...)?

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 

問題:如果我不使用COUNT (DISTINCT sv1.vid_id)(即只是COUNT(sv1.vid_id))我得到的遠遠超過了真數的數量。我已經在數據庫中驗證了這一點。有沒有人看到我要去哪裏錯了?有趣的是,如果我將聯接刪除到sv3(當然還有select語句的相應部分),問題就會消失。

[UPDATE]

下面是所涉及的兩個表的表結構:

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 

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 

示例輸出:

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

樣本數據和期望的結果可以幫助他人理解問題。 –

+0

更新....... – Utkanos

回答

2

在所有的可能性,你不要需要distinct。問題是你的加入。改爲使用條件彙總:

SELECT s.*, 
     COUNT(*) AS total_vids, #<-- the problem 
     GROUP_CONCAT(DISTINCT sv.context_node_id) AS topics, -- distinct is probably still needed here 
     COUNT(watched) AS vids_watched, 
     SUM(sv.date = CURDATE()) AS today 
FROM schedules s JOIN 
    schedule_vids sv 
    ON s.id = sv.schedule_id LEFT JOIN 
    school_users su 
    ON s.user_id = su.uid -- I'm guessing `user_id` comes from s 
WHERE s.user_id = ? AND s.id = ? 
GROUP BY s.id 
ORDER BY s.created DESC; 

如果您在沒有彙總的情況下運行查詢,則會看到發生了什麼。你正在獲得一個笛卡爾視頻產品,這就是爲什麼計數是關閉的。

+0

感謝您的幫助。但是,我收到了「字段列表」中的「未知列'sv3.date'」 - 無法像我那樣查看您定義'sv3'的位置,還是我想填補這一點? – Utkanos

+0

「SUM()」而不是「COUNT()」的原因是什麼? – Utkanos

+1

我認爲sv3應該是sv,它被遺漏了。 –