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は、要求された友人が少なくとも1人含まれている行にのみヒットするようにします。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 に答える