mysql - 选择在另一个表中没有特定值的项目

标签 mysql sql join subquery outer-join

我正在尝试选择在另一个表中没有特定值的项目,我能够通过使用子查询来实现我想要的结果,但是它非常慢,所以我想知道是否可以采取不同的做法...

SELECT
    content.*,
    (SELECT views
     FROM content_views
     WHERE content_views.content = content.record_num
    ) as views
FROM content
RIGHT JOIN watch_log ON content.record_num = watch_log.content
WHERE content.enabled = 1
    AND 24 NOT IN
        (SELECT niche
         FROM content_niches
         WHERE content_niches.content = content.record_num
        )
ORDER BY content.encoded_date
DESC LIMIT 0,6

我尝试使用 LEFT OUTER JOIN,但无法获得相同的结果...

SELECT
    content.*,
    (SELECT content_views.views
     FROM content_views
     WHERE content_views.content = content.record_num
    ) as views
FROM content
RIGHT JOIN watch_log ON content.record_num = watch_log.content
LEFT OUTER JOIN content_niches ON content.record_num = content_niches.content AND content_niches.niche = 24
WHERE content.enabled = 1
ORDER BY content.encoded_date
DESC LIMIT 0,6

最佳答案

混合左外连接和右外连接只是令人困惑。事实上,右连接并不是真正需要的。通常可以用左连接代替。在您的情况下,它可以被内部联接替换,因为 where 子句将其转换为内部联接。那么,怎么样:

SELECT c.*,
       (SELECT views
        FROM content_views cv
        WHERE cv.content =  c.record_num
       ) as views
FROM content c JOIN
     watch_log wl
     ON c.record_num = wl.content
WHERE c.enabled = 1 AND
      NOT EXISTS (SELECT 1
                  FROM content_niches cn
                  WHERE cn.content = c.record_num AND
                        cn.niche = 24
                 )
ORDER BY c.encoded_date DESC
LIMIT 0, 6;

为了提高性能,您需要索引:content(enabled,encoded_date,record_num)content_views(content,views)content_niches(content,niche).

注释:

  • 不要混合使用不同类型的外连接,除非您真的非常了解它们在做什么。
  • 使用表名称缩写的表别名。这使得查询更容易编写和阅读。
  • 无论您对格式的偏好如何,都不要在查询中以 DESC(或 ASC)开始一行;这是 ORDER BY 的修饰符。
  • NOT EXISTSNOT IN 更好。前者按照您期望的方式处理 NULL 值。如果存在 NULL 值,后者不会返回任何内容。

关于mysql - 选择在另一个表中没有特定值的项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35272586/

相关文章:

sql - 使用 JOIN 更新表

php - 使用 Laravel 获取从 offset 开始的所有行

php - PHP 中的 MySQL 访问类

php - 从哪里开始开发第一个数据库驱动的 Web 应用程序(长问题)?

mysql - SQL:如何总结几十年的计数?

php - 警告:mysqli::query():空查询

mysql - SQL:如何在不覆盖结果的情况下对表的同一列进行多个连接?

mysql - 从表中删除重复的行(每天的第一个时间戳除外)

php - while 循环中第一个数据丢失

apache-spark - Spark : Prevent shuffle/exchange when joining two identically partitioned dataframes