【问题标题】:MySQL query that selects non-friends of a user选择用户的非朋友的 MySQL 查询
【发布时间】:2019-10-08 23:23:35
【问题描述】:

我有以下 Mysql 数据库架构:

User(Id, FirstName, LastName, NickName, Etc.)
Request(SenderId, ReceiverId)
Friendship(Id1, Id2)

我认为友谊是一种无向关系,这意味着对于每一个友谊,我都会将它两次插入到 Friendship 表中。 (如果这不是一个好主意,请告诉我)。

我要检索的是一个用户列表,这些用户不是特定用户的朋友(让我将他命名为 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 有友谊或请求的元组,但朋友仍然出现,因为他们与其他用户有友谊!

提前致谢。

【问题讨论】:

  • 提供样本数据和期望的结果。

标签: mysql sql social-network-friendship


【解决方案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 子查询在一起的解决方案有更好的性能。

【讨论】:

  • 恐怕这只会返回根本没有朋友的用户。
  • @AhmedHammad 。 . .当然,它必须测试你想要的id。
【解决方案2】:

对联合列表使用左连接:

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'

【讨论】:

  • 工作得很好,除了它还返回 UserX 本人。谢谢。
【解决方案3】:

如果您从表“请求”和“友谊”中收集所有不同的 ID,然后从用户 ID 中选择上述列表中不可用的记录。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    相关资源
    最近更新 更多