Select 项在另一个 table 中没有特定值

Select items that doesn't have a specific value in another table

我正在尝试 select 在另一个 table 中没有特定值的项目,我能够通过使用子查询获得我想要的结果,但是它非常慢所以我想知道我是否可以做不同的事情...

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

混合使用左外连接和右外连接只会让人感到困惑。事实上, right join 并不是真正需要的。通常可以用left join代替。在你的情况下,它可以被内部连接替换,因为 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)

备注:

  • 不要混合使用不同类型的外部联接,除非您真的非常了解它们在做什么。
  • 使用table别名,即table名字的缩写。这使得查询更易于编写和阅读。
  • 无论您喜欢什么格式,都不要在查询中以 DESC(或 ASC)开始一行;这是 ORDER BY.
  • 的修饰符
  • NOT EXISTS 优于 NOT IN。前者以您期望的方式处理 NULL 值。如果有 NULL 个值,则后者 returns 没有。