多对多自引用select sql查询

时间:2010-10-27 21:10:48

标签: sql mysql select

我为两个用户之间的关系设置了一个简单的表(MySQL)。

 [User1Id] [User2Id]
  10        15
  14        10
  10        13

但是,我无法弄清楚如何以这样的方式进行SELECT,以便我可以获取被请求的用户的相反UserId。因此,如果我想获得ID为10的用户的所有关系,它将获取用户ID 15,14和13,并且理想情况下将users表与这些ID连接以获得这些用户的用户名。我目前的尝试不太理想:

 SELECT u1.username AS U1Username, 
        u2.username AS U2Username, 
        u1.userId AS U1UserId, 
        u2.userId AS U2UserId 
 FROM buddies b 
 LEFT JOIN users u1 on u1.userId=b.user2Id 
 LEFT JOIN users u2 on u2.userId=b.user1Id 
 WHERE b.user1Id=:1 OR b.user2Id=:1

然后在代码中过滤并重新排列。有没有办法让我可以做一个SQL查询来获取我需要的所有内容?

4 个答案:

答案 0 :(得分:3)

使用:

SELECT u.userid,
       u.username
  FROM USERS u
 WHERE EXISTS(SELECT NULL
                FROM BUDDIES b
               WHERE u.userid = b.user1id
                 AND b.user2id = 10)
    OR EXISTS(SELECT NULL
                FROM BUDDIES b
               WHERE u.userid = b.user2id
                 AND b.user1id = 10)

...或:

SELECT a.user1id,
       u.username
  FROM BUDDIES a
  JOIN USERS u ON u.userid = a.user1id
 WHERE a.user2id = 10
UNION 
SELECT b.user2id,
       u.username
  FROM BUDDIES b
  JOIN USERS u ON u.userid = b.user2id
 WHERE b.user1id = 10

UNION将删除重复项; UNION ALL删除重复项并加快速度。

答案 1 :(得分:2)

可能能够更好地进行优化,但我认为这可能有效:

SELECT username, userId FROM users 
WHERE 
    userId IN (SELECT user1Id FROM buddies WHERE user2Id={ID})
  OR
    userId IN (SELECT user2Id FROM buddies WHERE user1Id={ID})

答案 2 :(得分:1)

我提出了这个解决方案:

SELECT users.userId, users.username FROM users WHERE userId IN (
    SELECT CASE
        WHEN user2id = 10 THEN user1id
        WHEN user1id = 10 THEN user2id
    END AS id 
    FROM buddies WHERE (
        (buddies.User1Id = 10 AND buddies.User2Id != 10) OR 
        (buddies.User2Id = 10 AND buddies.user1Id != 10)
    )
)

答案 3 :(得分:0)

联盟是最容易阅读的解决方案,但是因为你要求不工会的答案。它可能会比UNION ALL慢,因为所有的CASE,如果你有自己的伙伴,你会得到两个记录。

 SELECT 
    Case When u1.userid = :1 Then u1.username Else u2.username End AS LookForUser, 
    Case When u1.userid = :1 Then u2.username Else u1.username End AS BuddyName, 
    Case When u1.userid = :1 Then u1.userid Else u2.userid End AS LookForUserID, 
    Case When u1.userid = :1 Then u2.userid Else u1.userid End AS BuddyID, 
 FROM buddies b 
 LEFT JOIN users u1 on u1.userId=b.user2Id 
 LEFT JOIN users u2 on u2.userId=b.user1Id 
 WHERE b.user1Id=:1 OR b.user2Id=:1