经典sql题(十一)查找共同好友或相互关注 二

在处理海量数据时,使用 JOIN 可能会导致性能瓶颈,特别是当参与 JOIN 的表非常大时,JOIN 操作通常需要扫描多个表,并且在连接条件上进行复杂的匹配,这会消耗大量的计算资源和时间。相反,使用聚合或过滤的方法可以减少数据处理的复杂性,从而提高性能。以下是使用不依赖于 JOIN 的方法找出互相关注用户对的方法

1. 问题背景

设想我们有一个名为 follow 的表,记录用户之间的关注关系。我们的目标是找出所有互相关注的用户对。比如,如果用户 A 关注了用户 B,而用户 B 也关注了用户 A,则我们可以认为这是一种双向关系。

2. 数据结构

假设我们的 follow 表结构如下:

from_userto_user
12
21
13
31
45
54
23

3. SQL 查询步骤解析

3.1 内部查询

我们首先需要通过一个内部查询生成一个唯一标识符,表示每对用户的关注关系。这个标识符将使我们能够识别出相同用户对的双向关系。

SELECT
    from_user,
    to_user,
    IF(from_user > to_user, 
       CONCAT(from_user, '-', to_user), 
       CONCAT(to_user, '-', from_user)) AS concat_users
FROM 
    follow;
结果
from_userto_userconcat_users
121-2
211-2
131-3
311-3
454-5
544-5
232-3

3.2 中间结果 - 聚合双向关系

接下来,我们需要利用窗口函数来计算每个 concat_users 的出现次数,从而识别出双向关系。

SELECT
    from_user,
    to_user,
    SUM(1) OVER(PARTITION BY concat_users) AS flag
FROM
    (
        SELECT
            from_user,
            to_user,
            IF(from_user > to_user, 
               CONCAT(from_user, '-', to_user), 
               CONCAT(to_user, '-', from_user)) AS concat_users
        FROM 
            follow
    ) t;
结果
from_userto_userflag
122
212
132
312
452
542
231
321

3.3 外部查询 - 筛选双向关系

最后,我们在外部查询中筛选出 flag = 2 的记录,这表明这些用户对之间存在双向关注关系。

SELECT
    t1.from_user,
    t1.to_user
FROM
    (
        SELECT
            from_user,
            to_user,
            SUM(1) OVER(PARTITION BY concat_users) AS flag
        FROM
            (
                SELECT
                    from_user,
                    to_user,
                    IF(from_user > to_user, 
                       CONCAT(from_user, '-', to_user), 
                       CONCAT(to_user, '-', from_user)) AS concat_users
                FROM 
                    follow
            ) t
    ) t1
WHERE
    t1.flag = 2;
最终结果
from_userto_user
12
21
45
54

根据上述查询结果,我们可以分析出每对用户之间的好友关系:

用户 1 和 用户 2 是好友。
用户 4 和 用户 5 是好友。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值