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

时间:2016-02-08 14:56:41

标签: 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

1 个答案:

答案 0 :(得分:0)

混合左右外连接只是令人困惑。事实上,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)

注意:

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