我有一个系统,允许用户创建要观看的视频时间表。以下 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
问题:如果我不使用COUNT (DISTINCT sv1.vid_id)
(即只是COUNT(sv1.vid_id)
)我得到的数字远远超过真实数字。我已经在数据库中验证了这一点。有人看到我哪里出错了吗?
有趣的是,如果我删除与 sv3 的连接(当然还有 select 语句的相应部分),问题就会消失。
[更新]
下面是涉及到的两个表的表结构:
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
最佳答案
很有可能,您不需要 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;
如果您在没有聚合的情况下运行查询,您将看到发生了什么。您得到的是视频的笛卡尔积,这就是计数不计的原因。
关于mysql - 为什么我在这个 MySQL 中需要 COUNT(DISTINCT ...)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43156114/