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 没有。
我正在尝试 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 没有。