2015-03-12 1 views
0

У меня есть эта таблица, которая представляет дружбуNOT IN не работает в тузде процедуры

+--------+--------+ 
| 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 | 
+------------+ 

Затем я создал еще одну процедуру, вызывающую первый и верный друг друзей

A й запрос возвращает следующее:

+------------+ 
| user_2 | 
+------------+ 
| 729611272 | 
| 527419864 | 
| 651861323 | 
| 676185145 | 
| 1036862839 | 
| 502741322 | 
| 546744626 | 
| 636845886 | 
| 652813833 | 
| 663713246 | 
| 682866129 | 
| 781419583 | 
| 845134109 | 
| 1355751897 | 
| 1359286892 | 
| 1275961636 | 
| 620972114 | 
| 509609160 | 
| 662123645 | 
| 1460283586 | 
+------------+ 

Так что ясно, что НЕ не работает, так как все значения getFriends находятся во втором наборе результатов.

Мне удалось получить результаты, которые я хотел, делая уродливые вещи, но все же, я хотел бы понять, что здесь не так. И нет NULL стоимость в любом месте.

Спасибо!

ответ

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); 
+0

Я хочу сказать вам, что это работает, но я получаю пустой набор, делающий то или другое ... Я действительно не понимаю его, поскольку друзья действительно являются подмножеством запроса с первым предложением WHERE , И я не знал, что IN (f.user_2) возвращает только один элемент, спасибо за указание, что мой sql ржавый. –

+0

Я действительно удивлен, что это не работает.Мне пришлось создать временную таблицу для хранения результата первого IN, а затем использовать NOT IN на этой таблице, что смешно. –

+0

Это интересно. Я просто запускал оба запроса по некоторым образцовым данным, и они отлично работали. Может быть, вы забыли назвать 'getFriends'? Ваш запрос, который вы опубликовали в вопросе, по-прежнему работает? – Ishamael

0

Я думал, что проблема может быть с временной таблицей, и я был прав. При выполнении запроса в MySQLWorkbench следующая ошибка была Ouput:

Error Code: 1137. Can't reopen table: 'friends' 

Так что я пошел в Интернете, чтобы проверить, есть ли ограничение на количество раз, временная таблица может быть использована в том же запросе и in fact there is.

Так что я могу просто временную таблицу в постоянную (и бросать ее каждый раз заранее), и все будет работать так, как ожидалось. sigh