我具有以下Mysql数据库架构:
User(Id, FirstName, LastName, NickName, Etc.)
Request(SenderId, ReceiverId)
Friendship(Id1, Id2)
我认为友谊是无方向性的关系,这意味着对于每个友谊,我都会将其两次插入到友谊表中。 (请让我知道这不是一个好主意)。
我要检索的是一个用户列表,这些用户不是特定用户的朋友(我叫他UserX),也没有正在/向他发送当前请求的人。
最初的试验使我想到了这一点
SELECT User.Id, User.NickName, User.Picture FROM User
LEFT JOIN Friendship A ON User.Id = A.Id1
LEFT JOIN Friendship B ON User.Id = B.Id2
LEFT JOIN Request C ON User.Id = C.Sender
LEFT JOIN Request D ON User.Id = D.Reciever
WHERE User.Id <> ?
当然,占位符是UserX的ID。
这是行不通的,因为尽管消除了与UserX有友谊或要求的元组,但朋友仍然出现是因为他们与其他用户有友谊!
谢谢。
答案 0 :(得分:1)
使用左联接到联合列表:
select *
from User u1
left join
(
select ID2 as id
from Friendships
where ID1 = 'UserX'
union all
select ID1
from Friendships
where ID2 = 'UserX'
union all
select Sender
from Request
where Receiver = 'UserX'
union all
select Receiver
from Request
where Sender = 'UserX'
) ux
on ux.id = u1.id
where ux.id is null
and ux.id <> 'UserX'
答案 1 :(得分:1)
如果您想要有效的解决方案,请多次使用not exists
:
select u.*
from user u
where not exists (select 1 from friendship f where f.id1 = u.id and f.id2 = ?) and
not exists (select 1 from friendship f where f.id2 = u.id and f.id1 = ?) and
not exists (select 1 from request r where r.SenderId = u.id and r.ReceiverId = ?) and
not exists (select 1 from request r where r.ReceiverId = u.id and r.SenderId = ?);
尤其是,这可以利用以下位置的索引:
friendship(id1, id2)
friendship(id2, id1)
request(SenderId, ReceiverId)
request(ReceiverId, SenderId)
与union
一起子查询的解决方案相比,这应该具有更好的性能。
答案 2 :(得分:0)
What if you collect all distinct IDs from table "request" and "Friendship" and then select records from Users ID not available in the above list.
SELECT Id, FirstName, LastName, NickName
FROM User
WHERE ID NOT IN
(
SELECT DSTINCT Id1 ID FROM Friendship
UNION
SELECT DSTINCT Id2 FROM Friendship
UNION
SELECT DSTINCT SenderId FROM Request
UNION
SELECT DSTINCT ReceiverId FROM Request
)A