我有这张代表友情的表
+--------+--------+
| user_1 | user_2 |
+--------+--------+
| 1 | 5 |
| 2 | 67 |
| 3 | 23 |
| ... | ... |
+--------+--------+
我的目标是创建一个程序,返回用户朋友的朋友(不包括朋友)。
我开始创建一个程序来返回给定用户的朋友
CREATE DEFINER=`user`@`localhost` PROCEDURE `getFriends`(IN `myuser` BIGINT(20))
NO SQL
BEGIN
DROP TABLE IF EXISTS friends;
CREATE TEMPORARY TABLE friends
SELECT user_2
FROM fb_friends
WHERE user_1=myuser;
END
此过程对用户534477793创建以下临时表
+------------+
| user_2 |
+------------+
| 527419864 |
| 580101923 |
| 620972114 |
| 651861323 |
| 662123645 |
| 676185145 |
| 682866129 |
| 718761310 |
| 729611272 |
| 1036862839 |
+------------+
然后我创建了另一个调用第一个并返回朋友的朋友的程序
CREATE DEFINER=`user`@`localhost` PROCEDURE `getFriendsOfFriends`(IN `myuser` BIGINT(20))
BEGIN
-- Creates the table friends
CALL getFriends(myuser);
SELECT DISTINCT(fb.user_2)
FROM fb_friends fb, friends f
-- This works
WHERE fb.user_1 IN (f.user_2)
-- This doesn't
AND fb.user_2 NOT IN (f.user_2);
END
查询返回以下内容:
+------------+
| user_2 |
+------------+
| 729611272 |
| 527419864 |
| 651861323 |
| 676185145 |
| 1036862839 |
| 502741322 |
| 546744626 |
| 636845886 |
| 652813833 |
| 663713246 |
| 682866129 |
| 781419583 |
| 845134109 |
| 1355751897 |
| 1359286892 |
| 1275961636 |
| 620972114 |
| 509609160 |
| 662123645 |
| 1460283586 |
+------------+
所以很明显 NOT IN 不起作用,因为来自getFriends
的所有值都在第二个结果集中。
我设法通过做丑陋的事情来获得我想要的结果但是,我仍然想知道这里有什么问题。顺便提一下,没有 NULL 值。
谢谢!
答案 0 :(得分:0)
这是因为f.user_2
中的NOT IN
只是一个用户,而不是整个用户。
正确的方法是
SELECT DISTINCT(fb.user_2)
FROM fb_friends fb, friends f
WHERE fb.user_1 IN (f.user_2)
AND fb.user_2 NOT IN (SELECT * FROM friends);
请注意,第一个IN
可以替换为=
运算符,因为IN
列表中只有一个元素。
或者您可以完全删除联接以使查询保持一致(但它可能会使性能回归)
SELECT DISTINCT(fb.user_2)
FROM fb_friends fb
WHERE fb.user_1 IN (SELECT * FROM friends)
AND fb.user_2 NOT IN (SELECT * FROM friends);
答案 1 :(得分:0)
我认为问题可能出在临时表上,我说得对。通过在MySQLWorkbench中执行查询,以下错误是输出:
Error Code: 1137. Can't reopen table: 'friends'
所以我上网查看临时表在同一查询和in fact there is中的使用次数是否有限制。
所以我可能只是将临时表变为永久表(并且每次都预先删除它),所有这些都将按预期工作。 叹息