MySQL连接类型用于同一个表中的记录

时间:2014-05-20 18:35:41

标签: mysql sql join outer-join

标题有点尴尬,但我会尽力解释我想要完成的事情。

我有一个名为Users的表,另一个名为Friends

Users表的抽象结构是:

+----+------+----------+----------+
| ID | Name | Username | Password |
+----+------+----------+----------+

Friends表有一个抽象结构,如:

+----+--------+----------+--------+
| ID | UserID | FriendID | Hidden |
+----+--------+----------+--------+

UserID是发送好友请求的用户的ID,FriendID是请求的收件人。如果收件人已选择隐藏请求,则隐藏列的值为1。

我想将这一切缩减为一个查询,到目前为止,我有两个单独的查询使用LEFT JOINRIGHT JOIN

查找已发送的请求和当前的朋友:

SELECT 
    *, 
    CASE 
       WHEN C.ID IS Null THEN "Request Sent" 
       ELSE "Friends" 
    END AS Status 
FROM
    (SELECT DISTINCT
         A.ID, A.Name, E.Hidden
     FROM
         Users A 
     INNER JOIN 
         Friends E ON A.ID = E.UserID
     WHERE
         A.ID in (SELECT UserID 
                  FROM Friends 
                  WHERE FriendID = "1" AND Deleted='No')) C
RIGHT JOIN
    (SELECT DISTINCT
         B.ID, B.Name, F.Hidden
     FROM
         Users B 
     INNER JOIN 
         Friends F ON B.ID = F.FriendID
     WHERE
         B.ID in (SELECT FriendID 
                  FROM Friends 
                  WHERE UserID = "1" AND Deleted = 'No')) D ON C.ID = D.ID

至于收到的朋友请求和当前的朋友:

SELECT *, CASE WHEN D.ID IS Null THEN "Wants to be your friend" ELSE "Friends" END AS Status FROM
(SELECT DISTINCT
A.ID, A.Name, E.Hidden
FROM
Users A INNER JOIN Friends E ON A.ID=E.UserID
WHERE
A.ID in (SELECT UserID FROM Friends WHERE FriendID = "1" AND Deleted='No')) C
LEFT JOIN
(SELECT DISTINCT
B.ID, B.Name, F.Hidden
FROM
Users B INNER JOIN Friends F ON B.ID=F.FriendID
WHERE
B.ID in (SELECT FriendID FROM Friends WHERE UserID = "1" AND Deleted='No')) D
ON C.ID=D.ID

如果我没有解释我的需要,下面的维恩图可能是一个重要的说明性推动。

Venn Diagram

请注意,为了构建查询,我选择了所有列,但我最后只需要朋友的姓名和ID。

1 个答案:

答案 0 :(得分:1)

在两个查询之间执行union allunion distinct,这将在一个表中返回所有结果。

SELECT *, D.ID, CASE WHEN D.ID IS Null THEN "Wants to be your friend" ELSE "Friends" END AS Status FROM
(SELECT DISTINCT
A.ID, A.Name, E.Hidden
FROM
Users A INNER JOIN Friends E ON A.ID=E.UserID
WHERE
A.ID in (SELECT UserID FROM Friends WHERE FriendID = "1" AND Deleted='No')) C
LEFT JOIN
(SELECT DISTINCT
B.ID, B.Name, F.Hidden
FROM
Users B INNER JOIN Friends F ON B.ID=F.FriendID
WHERE
B.ID in (SELECT FriendID FROM Friends WHERE UserID = "1" AND Deleted='No')) D
ON C.ID=D.ID
union all
SELECT *, D.ID, CASE WHEN C.ID IS Null THEN "Request Sent" ELSE "Friends" END AS Status FROM
(SELECT DISTINCT
A.ID, A.Name, E.Hidden
FROM
Users A INNER JOIN Friends E ON A.ID=E.UserID
WHERE
A.ID in (SELECT UserID FROM Friends WHERE FriendID = "1" AND Deleted='No')) C
RIGHT JOIN
(SELECT DISTINCT
B.ID, B.Name, F.Hidden
FROM
Users B INNER JOIN Friends F ON B.ID=F.FriendID
WHERE
B.ID in (SELECT FriendID FROM Friends WHERE UserID = "1" AND Deleted='No')) D
ON C.ID=D.ID