mysql - 从数据透视表中获取不重复的数据

标签 mysql sql

我有树 table 。 videos、categories 和 video_categories(基本上是视频和类别之间的数据透视表)。

我正在尝试获取所有没有特定类别的视频。问题是我的结果不止一次包含相同的视频,而我只需要一次。

这是我得到的

SELECT videos.* FROM videos
JOIN video_categories ON videos.id = video_categories.video_id
WHERE category_id NOT IN (64452, 1031, 32595, 1015, 26484, 1019)
ORDER BY downloads

我得到的结果是包含一个视频的次数与视频类别数相同。还有一件事是视频表有 55300 行,数据透视表 video_categories 有 400000 行,所以我不能只使用 DISTINCT 因为查询运行了大约 10 秒。

我从 PHP 调用此查询,由于分页,无法从检索到的类别中手动排除类别。

有什么建议吗?

编辑 一个视频可以有多个类别。所以它是多对多关系。

最佳答案

你目前的查询不仅效率低下而且是错误的(除了我认为是错字的 missing from 子句),当你运行时考虑一个视频有类别 1 和 1031:

SELECT videos.* FROM Videos
JOIN video_categories ON videos.id = video_categories.video_id
WHERE category_id NOT IN (64452, 1031, 32595, 1015, 26484, 1019)
ORDER BY downloads;

此视频将被退回,因为类别 1 不在提供的类别列表中。您需要做的是找到所有具有这些类别的视频,然后排除这些视频。我通常会使用 NOT EXISTS 来执行此操作,因为我认为它更合乎逻辑:

SELECT  v.*
FROM    Videos AS v
WHERE   NOT EXISTS
        (   SELECT  1
            FROM    video_categories AS vc
            WHERE   vc.video_id = v.id
            AND     vc.category_id IN (64452, 1031, 32595, 1015, 26484, 1019)
        );

然而,MySQL optimises this kind of query better using LEFT JOIN/IS NULL :

SELECT  v.*
FROM    Videos AS v
        LEFT JOIN video_categories AS vc
            ON vc.video_id = v.id
            AND vc.category_id IN (64452, 1031, 32595, 1015, 26484, 1019)
WHERE   vc.Video_ID IS NULL;

如果这仍然不快,那么您可能缺少逻辑索引。在您的 Videos 表中,ID 应该是聚类键,而在 video_categories 中,您应该有一个复合聚类键 (video_idcategory_id)。

关于mysql - 从数据透视表中获取不重复的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23937997/

相关文章:

javascript - 单击按钮显示/隐藏 colspan 特定行

php - 启动多个 PHP 进程

sql - 如何使用 CASE 语句设置局部变量

php - 从数据库创建的动态 ical 不起作用

MySQL:触发子句 "instead of update"

php - 使用 COUNT 函数仅计算 SQL 中的搜索结果

mysql - 一次插入多个表

mysql - 5 个表 -> 显示某些不同的行

mysql - 在 MySQL 中索引和查询分析表的最佳方式

c# - 向 SQL 数据库中插入新行