0

可能な限り SQL を使用して 2 つのデータ セットを比較したいと考えています。次のデータ構造を考慮してください。

tbl_users:
+---------+----------+
| user_id |   avatar |
+---------+----------+
|    1    | test.jpg |
|    2    | 1234.jpg |
+---------+----------+

tbl_shortlists:
+------+--------+
|  id  |  owner |
+------+--------+
|   1  |    1   |
|   2  |    2   |
+------+--------+

tbl_shortlist_items:
+---------+--------------+
| item_id | shortlist_id |
+---------+--------------+
|    1    |       1      |
|    2    |       1      |
|    3    |       1      |
|    1    |       2      |
|    2    |       2      |
+---------+--------------+   

を選択したいtbl_usersuser_idtbl_users。ユーザーが所有する候補リストには、現在の所有者avatarと同じものが 2 つ以上含まれています。item_idしたがって、上記のデータ構造で user_id 1 を検索していると仮定しましょう。ID の Shortlist は 1 と 2 つのアイテムshortlist_id(つまり、ユーザー 1 の shortlist) を共有しているため、 user_id= 2 とavatar= 1234.jpg を返したいと思います。

純粋なSQLでこれを行う方法について途方に暮れています。が使えるIN()のではないかと思っていたのですが、うまくいくかどうかはわかりません。

これは、私が望むものをもう少しよく説明するための疑似コードです。

user_id = 1 が所有するショートリストにある 2 つ以上の item_id を含むショートリストごとに、user_id とアバターを選択します。

4

1 に答える 1

3

SQL の場合と同様に、小さなセクションに分割すると役立ちます。つまり、最初に必要なのは、現在のユーザーが所有する短いリスト内のすべてのアイテムです。

SELECT  Item_ID
FROM    tbl_ShortList_Items
        INNER JOIN tbl_ShortLists
            ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE   Owner = 1 -- CURRENT USER

次に、同じアイテムを含む短いリストを持つすべてのユーザーが必要です。説明のためにINステートメントとして作成しますが、INNER JOIN の方がパフォーマンスが良い場合があります。

SELECT  Owner
FROM    tbl_ShortList_Items
        INNER JOIN tbl_ShortLists
            ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE   Item_ID IN 
        -- RESULTS FROM LAST QUERY START
        (   SELECT  Item_ID
            FROM    tbl_ShortList_Items
                    INNER JOIN tbl_ShortLists
                        ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
            WHERE   Owner = 1 -- CURRENT USER
        )   
        -- RESULTS FROM LAST QUERY END
AND     Owner != 1 -- CURRENT USER

GROUP BY次に、およびを追加して、これを 2 つ以上のものに制限する必要があります。HAVING

SELECT  Owner
FROM    tbl_ShortList_Items
        INNER JOIN tbl_ShortLists
            ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE   Item_ID IN 
        -- RESULTS FROM LAST QUERY START
        (   SELECT  Item_ID
            FROM    tbl_ShortList_Items
                    INNER JOIN tbl_ShortLists
                        ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
            WHERE   Owner = 1 -- CURRENT USER
        )   
        -- RESULTS FROM LAST QUERY END
AND     Owner != 1 -- CURRENT USER
GROUP BY Owner
HAVING  COUNT(DISTINCT tbl_ShortList_Items.Item_ID) > 1

tbl_users次に、これらの所有者のアバターを取得するために使用する必要があります

SELECT  User_ID, Avatar
FROM    tbl_Users
WHERE   User_ID IN 
        -- RESULTS FROM LAST QUERY START
        (   SELECT  Owner
            FROM    tbl_ShortList_Items
                    INNER JOIN tbl_ShortLists
                        ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
            WHERE   Item_ID IN 
                    (   SELECT  Item_ID
                        FROM    tbl_ShortList_Items
                                INNER JOIN tbl_ShortLists
                                    ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
                        WHERE   Owner = 1 -- CURRENT USER
                    )
            AND     Owner != 1 -- CURRENT USER
            GROUP BY Owner
            HAVING  COUNT(DISTINCT tbl_ShortList_Items.Item_ID) > 1
        )
        -- RESULTS FROM LAST QUERY END

私が言ったように、これを JOIN に再配置するとより最適化されると思いますが、この理論をテストしていません。

SELECT  User_ID, Avatar
FROM    tbl_Users
        INNER JOIN
        (   SELECT  Owner
            FROM    tbl_ShortList_Items
                    INNER JOIN tbl_ShortLists
                        ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
                    INNER JOIN
                    (   SELECT  Item_ID
                        FROM    tbl_ShortList_Items
                                INNER JOIN tbl_ShortLists
                                    ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
                        WHERE   Owner = 1 -- CURRENT USER
                    ) CurrentUserItems
                        ON CurrentUserItems.Item_ID = tbl_ShortList_Items.Item_ID
            WHERE   Owner != 1
            GROUP BY Owner
            HAVING  COUNT(DISTINCT tbl_ShortList_Items.Item_ID) > 1
        ) MatchUsers
            ON MatchUsers.Owner = tbl_Users.User_ID
于 2012-08-28T14:02:00.097 に答える