2015-10-30 139 views
1

我想過濾我的表,其中用戶在一個表中有一行,並且在另一個表中沒有行。這裏是我的表結構:INNER JOIN + LEFT JOIN(雙重過濾)

下面是一個SQL小提琴代替:http://sqlfiddle.com/#!9/6e27ed/2

CREATE TABLE users (
    user_id INT(11) AUTO_INCREMENT, 
    name VARCHAR(25), 
    PRIMARY KEY(user_id) 
); 

CREATE TABLE photos (
    photo_id INT(11) AUTO_INCREMENT, 
    user_id INT(11) NOT NULL, 
    PRIMARY KEY(photo_id) 
); 

CREATE TABLE blocked (
    user_id INT(11) NOT NULL, 
    blocked_id INT(11) NOT NULL 
); 

INSERT INTO users (name) 
VALUES ('returned'), ('not returned'), ('not returned'), ('not returned'); 

INSERT INTO photos (user_id) 
VALUES (1), (2); 

INSERT INTO blocked (user_id, blocked_id) 
VALUES (4, 2); 

下面是我想查詢:

SELECT u.*, min(p.photo_id) 
FROM users u 
INNER JOIN photos p using(user_id) 
LEFT JOIN blocked b ON b.user_id = 4 AND b.blocked_id = u.user_id 
WHERE u.user_id != 4 
GROUP BY u.user_id 
LIMIT 9; 

的示例數據可以很明顯的是什麼結果應該是,因爲在這個例子中「name」字段填充了"returned", "not returned",所以user-id 2仍然被返回,但是他應該被LEFT JOIN移除,因爲user-id 4在被阻止的區域中具有user-id 2, ID字段被阻止的桌子。

預期結果從表:

+---------+----------+-----------------+ 
| user_id | name | min(p.photo_id) | 
+---------+----------+-----------------+ 
|  1 | returned |    1 | 
+---------+----------+-----------------+ 

從查詢中收到結果:

+---------+--------------+-----------------+ 
| user_id |  name  | min(p.photo_id) | 
+---------+--------------+-----------------+ 
|  1 | returned  |    1 | 
|  2 | not returned |    2 | 
+---------+--------------+-----------------+ 

回答

1

這是很難回答這個問題,因爲我看你比較blocked_id = USER_ID,雖然在被阻止的表,你也有一個user_id列。只有你會知道這一點。

但考慮以下

SELECT u.*, min(p.photo_id),b.* 
FROM users u 
INNER JOIN photos p using(user_id) 
LEFT JOIN blocked b ON b.user_id = 4 AND b.blocked_id = u.user_id 
WHERE u.user_id != 4 and b.user_id is null 
GROUP BY u.user_id 
LIMIT 9; 

+---------+----------+-----------------+---------+------------+ 
| user_id | name  | min(p.photo_id) | user_id | blocked_id | 
+---------+----------+-----------------+---------+------------+ 
|  1 | returned |    1 | NULL |  NULL | 
+---------+----------+-----------------+---------+------------+ 

它通過揭示的B開啓聲納。*列添加與where子句的第4位列5和混亂。

編輯

盪滌生產

SELECT u.*, min(p.photo_id) 
FROM users u 
INNER JOIN photos p using(user_id) 
LEFT JOIN blocked b ON b.user_id = 4 AND b.blocked_id = u.user_id 
WHERE u.user_id != 4 and b.user_id is null 
GROUP BY u.user_id 
LIMIT 9; 
+0

'blocked_id = u.user_i d'是爲了檢查被檢查的當前用戶是否被選擇的用戶阻塞(在這種情況下爲'4')。沒有透露'b。*'列的情況下沒有辦法做到這一點?這不是一個巨大的問題,但它有點討厭。 – Hobbyist

+1

我把它們放在那裏來展示它。它們不屬於你使用它製作的結果集!因此,在'where'中使用em,不要在命令行1上顯示em。 – Drew

0

我想你想WHERE b.blocked_id IS NULL返回尚未被用戶4

-1

你可以試試這個用戶..

SELECT u.*, min(p.photo_id) 
FROM users u 
INNER JOIN photos p using(user_id) 
LEFT JOIN blocked b ON b.blocked_id = u.user_id 
GROUP BY u.user_id having min(p.photo_id)<=all(select min(p.photo_id) FROM users u 
INNER JOIN photos p using(user_id) 
LEFT JOIN blocked b ON b.blocked_id = u.user_id 
GROUP BY u.user_id) 
;