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,返回B和G的SQL是什么?

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

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)

以防万一我在寻找只有 1,2,3 存在的 chat_id ......

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很快(在sqlite上)

提前谢谢了!

4

2 回答 2

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 JOINs确保它只命中至少有一个请求的朋友进入的行。matchedFriends 计数检查找到了多少请求的朋友。

然后,totalFriends 计数会检查该聊天中总共有多少朋友。

最后 HAVING 首先确定有 2 个匹配的好友,然后检查好友总数是否等于匹配好友的数量。

这将要求您提供朋友列表和您正在寻找的朋友的数量,但应该是有效的。

为了提高效率,有一个索引(chat_id,friend_id)(如果你还没有,假设在撰写本文时它是一个 2 部分的 PK)

于 2012-04-20T10:37:52.447 回答
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。

于 2012-04-20T10:20:35.840 回答