5

私は4つのテーブルを持っています

    users
    |  id  |Username|
    |   1  |  John  |
    |   2  |  Mike  |
    |   3  |  Alex  |

    user_contacts
    | user_id  |contact_id|
    |   1      |    2     |
    |   1      |    3     |
    |   2      |    3     |

    contact_groups
    | id  |  Group name  |
    |  1  |    Group 1   |  
    |  2  |    Group 2   |
    |  3  |    Group 3   |

    user_contact_groups
    | user_id  |contact_group_id|
    |   1      |    1           |
    |   1      |    2           |
    |   3      |    2           |

idが実行したいのは、連絡先グループ1および3に属するユーザー、またはユーザー1の連絡先(テーブル:user_contacts)をプルすることです。以下はコードですが、クエリが空であることが返されます

SELECT DISTINCT a.* from  users as a 
WHERE EXISTS (SELECT * FROM user_contacts as b 
    WHERE b.user_id = 1) OR 
    (a.id IN (select c.user_id 
         FROM user_contact_groups as c 
            WHERE c.contact_group_id IN (1,3)));
4

2 に答える 2

6

これは私がそれを行う方法であり、最も最適なはずです:

SELECT DISTINCT u.*
FROM users u
LEFT OUTER JOIN user_contacts c ON u.id = c.contact_id 
    AND c.user_id = 1
LEFT OUTER JOIN user_contact_groups g ON u.user_id = g.user_id 
    AND g.contact_group_id IN (1,3)
WHERE c.id IS NOT NULL OR g.id IS NOT NULL

EXISTS を使用したい場合は、もちろんこれを回避できますが、クエリでインデックスを使用できない場合があります (このクエリの DISTICT を削除できます)。

SELECT *
FROM users u
WHERE EXISTS
(
    SELECT 1
    FROM user_contacts c 
    WHERE c.contact_id = u.id
    AND c.user_id = 1
)
OR EXISTS
(
    SELECT 1
    FROM user_contact_groups g 
    WHERE g.user_id = u.user_id
    AND g.contact_group_id IN (1,3)
)

EXPLAIN を実行して、どちらが RDBMS に適しているかを確認することをお勧めします。

于 2012-12-20T02:38:18.657 に答える
3

サブクエリを実行する代わりに、左結合を実行できます

SELECT DISTINCT a.*
FROM users as a
LEFT JOIN user_contacts as b ON a.id = b.user_id AND a.id = 1
LEFT JOIN user_contact_groups as c on c.user_id = a.id AND c.contact_group_id IN (1,3)
WHERE b.user_id IS NOT NULL OR c.user_id IS NOT NULL

これをテストするために目の前にSQLはありませんが、正しい結果が得られると思います

于 2012-12-20T02:36:29.700 に答える