2012-04-20 78 views
3

這似乎很簡單,但它開始變得尷尬。選擇沒有其他行匹配的行

假設我們有一個包含表...

+---------+-----------+ 
| chat_id | friend_id | 
+---------+-----------+ 
| A  |   1 | 
| A  |   2 | 
| A  |   3 | 
| B  |   1 | 
| B  |   2 | 
| C  |   1 | 
| C  |   2 | 
| C  |   3 | 
| D  |   1 | 
| D  |   2 | 
| D  |   3 | 
| D  |   4 | 
| D  |   5 | 
| E  |   0 | 
| E  |   1 | 
| E  |   2 | 
| E  |   3 | 
| E  |   4 | 
| E  |   5 | 
| E  |   6 | 
| E  |   7 | 
| F  |   0 | 
| F  |   1 | 
| G  |   1 | 
| G  |   2 | 
+---------+-----------+ 

我希望只選擇有friend_ids 1和2,沒有其他friend_id那些chat_id,會是什麼SQL是讓B和G返回?

到目前爲止,我想出最好的是:

SELECT DISTINCT a.chat_id, COUNT(*) 
FROM tt2 a 
LEFT JOIN tt2 b 
ON a.chat_id = b.chat_id 
AND b.friend_id NOT IN (1,2) 
WHERE a.friend_id in (1,2) 
and b.chat_id IS NULL GROUP BY a.chat_id HAVING COUNT(*) = 2; 

+---------+----------+ 
| chat_id | count(*) | 
+---------+----------+ 
| B  |  2 | 
| G  |  2 | 
+---------+----------+ 
2 rows in set (0.00 sec) 

而且萬一我正在尋找chat_id只有1,2,3 ......存在

SELECT DISTINCT a.chat_id, COUNT(*) 
FROM tt2 a 
LEFT JOIN tt2 b 
ON a.chat_id = b.chat_id 
AND b.friend_id not in (1,2,3) 
WHERE a.friend_id IN (1,2,3) 
AND b.chat_id IS NULL 
GROUP BY a.chat_id 
HAVING COUNT (*) = 3; 

+---------+----------+ 
| chat_id | count(*) | 
+---------+----------+ 
| A  |  3 | 
| C  |  3 | 
+---------+----------+ 

但是這個表格可能會變得很龐大,我需要SQL很快,有沒有人知道更好的方法?

要嘗試和澄清......我得到給出一堆friend_id的和我想要得到chat_id其中只有那些friend_id爲chat_id存在....與SQL是快速(上源碼)

非常感謝提前!

回答

1

這裏的,應該是能夠限制

SELECT 
    d.chat_id, 
    COUNT(DISTINCT s.friend_id) AS matchedFriends, 
    COUNT(DISTINCT d.friend_id) AS totalFriends 
FROM tt2 AS d 
INNER JOIN tt2 AS s 
    ON s.chat_id = d.chat_id 
    AND s.friend_id IN (1,2) 
GROUP BY d.chat_id 
HAVING matchedFriends = 2 
AND totalFriends = matchedFriends 

的INNER JOIN s確保它僅命中已經得到了所請求的朋友至少一個行所需的數據量的選項。該matchedFriends計數會檢查找到多少個請求的朋友。

totalFriends count然後檢查總共有多少朋友在該聊天中。

最後,HAVING首先確定有2個匹配的朋友,然後檢查總共的朋友數量等於匹配的朋友數量。

這將需要您提供朋友列表和您正在尋找的許多朋友,但應該是有效的。

爲了提高效率,對(chat_id,friend_id)索引(如果你還沒有,假設它是在寫作時有2部分PK)

+1

愛一個我從未見過的人是不是很奇怪?......感謝兄弟。 – jambags 2012-04-20 10:53:08

0

試試這個:

SELECT chat_id, GROUP_CONCAT(DISTINCT friend_id ORDER BY friend_id) AS friends 
FROM table_1 
GROUP BY chat_id 
HAVING friends = '1,2' 

注:本作品在MySQL,但我懷疑這會在sqlite的工作。

+0

我不認爲這是在大數據量 – 2012-04-20 10:25:45

+0

建議我喜歡它......唯一的問題是,它會進行全表掃描:-( – jambags 2012-04-20 10:28:27

+0

不可避免的要誠實點,雖然調查替代品 – 2012-04-20 10:33:58