所以,我们说我有一个users
表和一个pages
表。让我们说我想让用户隐藏/忘记/忽略某些页面。在这一点上,我可以想到两种可能的方法:
null
匹配的外部联接:我可以创建一个单独的ignored_pages
表,列user_id
和page_id
,当ID为1的用户忽略ID为2的页面时写入INSERT INTO ignored_pages (user_id, page_id) VALUES (1,2);
然后我可以运行像SELECT pages.* FROM pages LEFT OUTER JOIN ignored_pages ON pages.id = ignored_pages.page_id WHERE ignored_pages.user_id = 1 AND ignored_pages.id IS NULL;
编辑: Joe Stefanelli指出我的查询中有错误。它应该是SELECT pages.* FROM pages LEFT OUTER JOIN ignored_pages ON pages.id = ignored_pages.page_id AND ignored_pages.user_id = 1 WHERE ignored_pages.id IS NULL;
NOT IN
:我可以使用相同的多对多表,然后运行类似SELECT pages.* FROM pages WHERE page_id NOT IN (SELECT page_id FROM ignored_pages WHERE user_id = 1);
的内容。
是否有最佳做法或一系列经验法则或(可能)比我所采取的方法更好地解决这个问题?
答案 0 :(得分:1)
您的最佳表现实际上可能是NOT EXISTS
SELECT p.*
FROM pages p
WHERE NOT EXISTS(SELECT 1
FROM ignored_pages
WHERE user_id = 1
AND page_id = p.id);
如果您决定坚持使用LEFT JOIN
选项,则需要更正该查询以在连接条件而不是user_id
子句上测试WHERE
。
SELECT pages.*
FROM pages
LEFT OUTER JOIN ignored_pages
ON pages.id = ignored_pages.page_id
AND ignored_pages.user_id = 1
WHERE ignored_pages.id IS NULL;
答案 1 :(得分:1)
为获得最佳效果,您应使用NOT EXISTS
SELECT pages.*
FROM pages
WHERE NOT EXISTS(
SELECT NULL
FROM ignored_pages
WHERE user_id = 1 AND ignored_pages.page_id = pages.page_id)
答案 2 :(得分:1)
答案 3 :(得分:0)
This page对使用LEFT OUTER JOIN和NOT EXISTS进行了很好的比较。该页面上的related link显示NOT EXISTS与NOT IN相比或更快,至少对于该博客上的示例案例而言。第一个链接显示NOT EXISTS的执行速度几乎是LEFT OUTER JOIN的两倍(cpu周期和执行时间),只要你有一个索引就可以加入/匹配所有列。
ignored_pages的索引可能如下所示:
CREATE UNIQUE CLUSTERED INDEX IX_Ignored_Pages ON ignored_pages (user_id, page_id);
适应您的代码,NOT EXISTS语法看起来像这样:
SELECT p.*
FROM pages p
WHERE NOT EXISTS (
SELECT 1
FROM ignored_pages i
WHERE i.user_id = @user_id
AND i.page_id = p.page_id
);