SQL面试题4:相互关注问题
引言
在社交媒体和各类社区平台蓬勃发展的当下,用户之间的关系网络成为了平台运营和数据分析的关键部分。相互关注作为一种重要的社交关系,不仅反映了用户之间的紧密程度,还对平台的社交生态、内容传播等方面有着深远影响。本文将聚焦于 SQL 在处理相互关注问题上的应用,帮助大家深入理解如何通过 SQL 语言来分析和挖掘这类社交关系数据,为相关从业者应对面试以及实际工作中的数据处理需求提供有力支持。
场景介绍
(一)社交平台的发展与相互关注的重要性
如今,社交平台已经渗透到人们生活的方方面面。从以分享生活点滴为主的朋友圈,到专注于知识交流的知乎,再到以兴趣爱好为纽带的抖音等平台,用户数量数以亿计。在这些平台中,相互关注的关系构建起了一个个复杂的社交圈子。对于平台运营者而言,了解用户之间的相互关注情况,可以更好地进行用户画像分析、个性化推荐内容,提升用户体验和平台活跃度。例如,在电商社交平台上,相互关注的用户之间可能有着相似的购物偏好,平台可以根据这一特点向他们推荐相关商品,促进交易转化。对于内容创作者来说,粉丝之间的相互关注关系有助于内容的快速传播,扩大影响力。
(二)相互关注问题在数据分析中的价值
从数据分析的角度来看,相互关注数据蕴含着丰富的信息。通过分析相互关注的用户群体特征,可以发现不同兴趣群体的聚集模式,为市场细分提供依据。同时,研究相互关注关系的动态变化,如新增相互关注的趋势、某些用户群体之间相互关注的增长速度等,能够及时洞察平台社交生态的演变,为平台的战略决策提供数据支撑。
题目描述
现有一份用户关注关系的数据表,记录了用户之间的关注行为信息,包含以下字段:
follower_id
:表示关注者的用户编号,用于唯一标识发起关注行为的用户。
followed_id
:表示被关注者的用户编号,用于唯一标识受到关注的用户。
根据上述信息,需要完成以下任务:
- 统计平台上相互关注的用户对数。
- 分析每个用户拥有的相互关注好友数量,即有多少其他用户与该用户相互关注。
数据准备与代码实现
数据准备
CREATE TABLE follow_relation_tb (follower_id INT,followed_id INT
);INSERT INTO follow_relation_tb VALUES
(1, 2),
(2, 1),
(1, 3),
(3, 4),
(4, 3),
(5, 6);
1. 统计平台上相互关注的用户对数
思路一:自连接(常规思路)
- 思路:通过自连接,将原表与自身关联,匹配互为关注关系的记录。
- 注意:去重,确保每对相互关注用户数只出现一次。
SELECT COUNT(DISTINCT a.follower_id, a.followed_id) AS mutual_follow_count
FROM follow_relation_tb a
JOIN follow_relation_tb b ON a.follower_id = b.followed_id
AND a.followed_id = b.follower_id
# 去重,确保每对相互关注用户数只出现一次
WHERE a.follower_id < a.followed_id;
思路二:UNION ALL + 分组统计法
- 思路:将原表与反转后的表合并,统计每组用户对出现的次数为2的记录。
SELECT follower_id,followed_id
FROM (SELECT follower_id, followed_id, COUNT(*) AS cntFROM (SELECT follower_id, followed_id FROM follow_relation_tbUNION ALLSELECT followed_id, follower_id FROM follow_relation_tb) tGROUP BY follower_id, followed_idHAVING cnt = 2
) tmp
WHERE follower_id < followed_id;
思路三:排序拼接法(优化思路)
思路:将用户对按字典序拼接为统一格式,统计出现次数为2的记录。
SELECT distinct CASE WHEN user1 < user2 THEN user1 ELSE user2 END AS user1,CASE WHEN user1 > user2 THEN user1 ELSE user2 END AS user2
FROM (SELECT followed_id AS user1, follower_id AS user2,COUNT(*) OVER (PARTITION BY CONCAT_WS('-',CAST(LEAST(followed_id, follower_id) AS STRING),CAST(GREATEST(followed_id, follower_id) AS STRING))) AS cntFROM follow_relation_tb
) t
WHERE cnt >= 2;
思路四:哈希函数与窗口函数结合(高阶优化)
- 思路:通过哈希函数生成唯一标识,结合窗口函数判断是否存在互相关注。
- 具体步骤:先将用户对进行统一的哈希处理,然后统计每个用户对出现的次数,标记出相互关注的用户对,最后筛选出处于相互关注关系中的被关注者的 ID。
SELECT DISTINCT follower_id,followed_id
FROM (SELECT follower_id,followed_id, IF(COUNT(fan_pair) OVER (PARTITION BY fan_pair) >= 2, 1, 0) AS is_mutualFROM (SELECT followed_id,follower_id,IF(followed_id < follower_id, HASH(followed_id, follower_id), HASH(follower_id, followed_id)) AS fan_pairFROM follow_relation_tb) t
) t2
WHERE is_mutual = 1;
四种思路对比
时间复杂度 | 空间复杂度 | 适用场景 | 优缺点 | |
---|---|---|---|---|
自连接法 | O(n²) | 高 | 小数据量,逻辑简单 | 优点:逻辑直观,适合数据量较小的场景 缺点:自连接可能导致数据膨胀,尤其在大数据量下性能较差。 |
UNION ALL + 分组 | O(nlogn) | 中 | 大数据量,避免JOIN | 优点:避免JOIN操作,适合大数据场景 缺点:UNION ALL导致数据量翻倍,可能增加计算成本 |
排序拼接法 | O(n) | 低 | 超大数据量,需快速响应 | 仅需一次表扫描,利用窗口函数减少计算量 |
哈希与窗口函数结合 | O(n) | 低 | 海量数据,高性能要求 | 利用哈希函数减少字符串拼接开销,性能更优 |
2. 分析每个用户拥有的相互关注好友数量
步骤与思路:
- 先通过自连接找到所有相互关注的关系,
- 然后使用
GROUP BY
对用户进行分组,再利用COUNT(DISTINCT)
函数统计每个用户对应的相互关注好友数量。 - 注意:由于相互关注关系会在连接结果中出现两次(如用户 1 和用户 2 相互关注,会有(1, 2)和(2, 1)两条记录),所以在统计时要使用
DISTINCT
避免重复计算。
SELECT a.follower_id AS user_id, COUNT(DISTINCT b.follower_id) AS mutual_follow_friends_count
FROM follow_relation_tb a
JOIN follow_relation_tb b ON a.follower_id = b.followed_id AND a.followed_id = b.follower_id
GROUP BY a.follower_id;
针对用户量较大的表处理相互关注问题的效率优化:索引优化和分区表
- 索引优化
在 follower_id 和 followed_id 列上创建复合索引。索引可以加快查询时的查找速度,因为数据库可以直接通过索引定位到符合条件的记录,而不需要全表扫描。
CREATE INDEX idx_follow_relation ON follow_relation_tb (follower_id, followed_id);
- 分区表
如果数据量非常大,可以考虑使用分区表。例如按照 follower_id 的范围进行分区,这样在查询时可以只扫描相关分区,减少扫描的数据量。
-- 创建分区表
CREATE TABLE follow_relation_tb (follower_id INT,followed_id INT
)
PARTITION BY RANGE (follower_id) (PARTITION p0 VALUES LESS THAN (1000),PARTITION p1 VALUES LESS THAN (2000),-- 可以根据实际情况添加更多分区PARTITION pn VALUES LESS THAN MAXVALUE
);
延伸问题
延伸问题1:如何避免重复记录(如(A,B)和(B,A)视为同一对)?
- 问题场景:查询结果中需要确保每对用户只出现一次(按字典序排列)。
- 优化点:
- 使用
LEAST
和GREATEST
标准化用户对顺序,避免重复。 - 通过
GROUP BY
聚合减少数据量,结合HAVING
筛选互关对。
- 使用
SELECTLEAST(followed_id, follower_id) AS user1,GREATEST(followed_id, follower_id) AS user2
FROM follow_relation_tb
GROUP BY user1, user2
HAVING COUNT(DISTINCT CASEWHEN followed_id = user1 THEN follower_idELSE followed_id
END) = 2;
延伸问题2:如何快速判断某个用户(如用户A)的互关用户列表
- 问题场景:给定用户A,高效查询与其互相关注的用户。
- 优化点:
- 为
(from_user, to_user)
建立联合索引,避免全表扫描。 - 使用
IN
子查询将操作转换为索引覆盖查询。
- 为
SELECTfollower_id AS mutual_user
FROM follow_relation_tb
WHERE followed_id = 'A'
AND follower_id IN (SELECT followed_idFROM follow_relation_tbWHERE follower_id = 'A'
);
其他
- 延伸问题3:如何统计全平台用户的平均互关率?
- 问题场景:计算所有用户中,存在互相关注的用户占比。
- 延伸问题4:如何在大数据量下分页查询互关用户对?
- 问题场景:分页查询互关用户列表(如每页1000条)。
- 优化点:
- 用ROW_NUMBER()生成游标替代OFFSET,避免深度分页的性能问题。
- 预先聚合互关对减少计算量。
- 延伸问题5:如何实时监控新产生的互关对?
- 问题场景:实时检测新产生的互关关系(如用于消息推送)。
- 优化点:
- 触发器确保实时性,但需注意高并发下的性能问题。
- 替代方案:通过消息队列异步处理,降低数据库压力。
高频优化技巧总结
- 索引设计:
必建索引:(from_user, to_user)的联合索引。
可选优化:为(LEAST(from_user, to_user), GREATEST(from_user, to_user))建立生成列索引。 - 避免全表扫描:
使用EXISTS替代IN子查询;通过覆盖索引减少回表操作。 - 分治策略:
按用户ID哈希分桶,并行处理不同桶的数据;使用分区表(如按时间或用户范围分区)。 - 内存优化:
调整数据库的sort_buffer_size和join_buffer_size;使用临时表存储中间结果。 - 业务妥协:
异步计算:非实时场景可将结果写入缓存表定期更新。
概率统计:使用APPROX_COUNT_DISTINCT等近似函数加速计算。
面试回答技巧
- 强调场景适配:如“如果数据量在千万级,我会优先选择分桶+哈希的方式”。
- 结合执行计划:提到
EXPLAIN
分析索引使用情况。 - 容错设计:如处理重复数据、事务隔离级别的影响。
- 扩展思考:提及NoSQL方案(如Redis的集合操作)作为对比,体现技术广度。
相关文章:
SQL面试题4:相互关注问题
引言 在社交媒体和各类社区平台蓬勃发展的当下,用户之间的关系网络成为了平台运营和数据分析的关键部分。相互关注作为一种重要的社交关系,不仅反映了用户之间的紧密程度,还对平台的社交生态、内容传播等方面有着深远影响。本文将聚焦于 SQL…...

ArcGIS基础知识之ArcMap基础设置——ArcMap选项:常规选项卡设置及作用
作为一名 GIS 从业者,ArcMap 是我们日常工作中不可或缺的工具。对于初学者来说,掌握 ArcMap 的基础设置是迈向 GIS 分析与制图的第一步。今天,就让我们一起深入了解 ArcMap 选项中常规选项卡的各个设置,帮助大家更好地使用这款强大的软件。 在 ArcMap 中,常规选项卡是用户…...
jvm 线程监控调试
文章目录 前言一、使用JDK工具转储线程文件(如jstack)1. 找到Java进程的PID:2. 使用jstack生成线程转储文件:3.验证生成的线程转储文件:二、分析文件1.使用在线工具进行分析上传thread-dump文件,等待解析完成2.查看分析结果总结前言 提示:使用jdk自带工具转储线程监控文…...
25、深度学习-自学之路-卷积神经网络基于MNIST数据集的程序展示
import keras #添加Keraskuimport sys,numpy as np from keras.utils import np_utilsimport osfrom keras.datasets import mnist print("licheng:""20"\n) np.random.seed(1)(x_train,y_train),(x_test,y_test) mnist.load_data() #第一次…...

【C++】解锁<list>的正确姿势
> 🍃 本系列为初阶C的内容,如果感兴趣,欢迎订阅🚩 > 🎊个人主页:[小编的个人主页])小编的个人主页 > 🎀 🎉欢迎大家点赞👍收藏⭐文章 > ✌️ 🤞 …...
Qt中的事件
写一个 可以拖动的按钮 DraggablePushButton.h 头文件 #ifndef DRAGGABLEPUSHBUTTON_H #define DRAGGABLEPUSHBUTTON_H#include <QPushButton> #include <QMouseEvent>class DraggablePushButton : public QPushButton {Q_OBJECTpublic:explicit DraggablePushBu…...

变化检测相关论文可读list
一些用得上的: 遥感变化检测常见数据集https://github.com/rsdler/Remote-Sensing-Change-Detection-Dataset/ 代码解读:代码解读 | 极简代码遥感语义分割,结合GDAL从零实现,以U-Net和建筑物提取为例 NeurIPS2024: https://mp.w…...
Ansible中playbook的变量
变量 playbook的变量有以下几种 在playbook中用户自定义的变量远程主机中由Ansible收集的变量在文件模板中使用的上述两种变量把任务结果作为一个变量使用,叫注册变量用户在执行playbook时,通过命令行传入的变量,叫做额外变量 在playbook中…...

亚信安全正式接入DeepSeek
亚信安全致力于“数据驱动、AI原生”战略,早在2024年5月,推出了“信立方”安全大模型、安全MaaS平台和一系列安全智能体,为网络安全运营、网络安全检测提供AI技术能力。自2024年12月DeepSeek-V3发布以来,亚信安全人工智能实验室利…...

相似性图相关性重构网络用于无监督跨模态哈希
《Similarity Graph-correlation Reconstruction Network for unsupervised cross-modal hashing》 摘要1. 引言2. 相关工作2.1. 监督跨模态哈希方法2.2. 无监督跨模态哈希方法 3. 方法论3.1 问题定义3.2 特征提取3.3 模态内关系图构建3.4. 局部关系图重置3.5. 跨模态关系图构建…...
【Bug】属性 PackageVersion 应在所有目标框架中具有单个值,但却具有以下值
文章目录 问题问题代码原因解决处理Bug的具体步骤 问题 严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) NU1105 无法读取“x”的项目信息: 属性 PackageVersion 应在所有目标框架中具有单个值,但却具有以下值: 1.0.0, 1.0.5 x (net8.0-android), x (net8.…...

C++ Primer 类型转换
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...

【CS61A 2024秋】Python入门课,全过程记录P7(Week13 Macros至完结)【完结撒花!】
文章目录 关于新的问题更好的解决方案Week13Mon Macros阅读材料Lab 11: Programs as Data, MacrosQ1: WWSD: QuasiquoteQ2: If ProgramQ3: Exponential PowersQ4: Repeat Wed SQL阅读材料Disc 11: MacrosQ1: Mystery MacroQ2: Multiple AssignmentQ3: Switch Optional Contest:…...

SSH隧道+Nginx:绿色通道详解(SSH Tunnel+nginx: Green Channel Detailed Explanation)
SSH隧道Nginx:内网资源访问的绿色通道 问题背景 模拟生产环境,使用两层Nginx做反向代理,请求公网IP来访问内网服务器的网站。通过ssh隧道反向代理来实现,重点分析一下nginx反代的基础配置。 实验环境 1、启动内网服务器的tomca…...

LabVIEW用户界面设计原则
在LabVIEW开发中,用户界面(UI)设计不仅仅是为了美观,它直接关系到用户的操作效率和体验。一个直观、简洁、易于使用的界面能够大大提升软件的可用性,尤其是在复杂的实验或工业应用中。设计良好的UI能够减少操作错误&am…...

Datawhale 数学建模导论二 2025年2月
第6章 数据处理与拟合模型 本章主要涉及到的知识点有: 数据与大数据Python数据预处理常见的统计分析模型随机过程与随机模拟数据可视化 本章内容涉及到基础的概率论与数理统计理论,如果对这部分内容不熟悉,可以参考相关概率论与数理统计的…...
SQL CASE表达式的用法
SQL CASE表达式的用法 一、CASE表达式的基础语法简单CASE表达式搜索CASE表达式 二、简单CASE表达式的应用示例三、搜索CASE表达式的应用示例四、CASE表达式在聚合函数中的应用五、嵌套CASE表达式的应用 今天在也无力用到了CASE表达式,于是有了这篇博客,C…...

趣味魔法项目 LinuxPDF —— 在 PDF 中启动一个 Linux 操作系统
最近,一位开源爱好者开发了一个LinuxPDF 项目(ading2210/linuxpdf: Linux running inside a PDF file via a RISC-V emulator),它的核心功能是在一个 PDF 文件中启动并运行 Linux 操作系统。它通过巧妙地使用 PDF 文件格式中的 Ja…...

win32汇编环境,窗口程序使用跟踪条(滑块)控件示例一
;运行效果 ;win32汇编环境,窗口程序使用跟踪条(滑块)控件示例一 ;生成2条横的跟踪条,分别设置不同的数值范围,设置不同的进度副度的例子 ;直接抄进RadAsm可编译运行。重要部分加备注。 ;下面为asm文件 ;>>>>>>>>>>>>>>>>>…...

mars3d接入到uniapp的时候ios上所有地图的瓦片都无法加载解决方案
用的是【Mars3d】官网的uniapp的仓库,安卓没有问题,但是ios的不行 相关链接 mars3d-uni-app: uni-app技术栈下的Mars3D项目模板 解决方案:感觉所有图片请求全被拦截了 uniapp的ios内核不允许跨域,需要先把瓦片下载后转base64&…...

双碳时代,能源调度的难题正从“发电侧”转向“企业侧”
安科瑞刘鸿鹏 摘要 在“双碳”战略和能源结构转型的大背景下,企业储能电站逐步成为提升能源利用效率、增强用能韧性的重要手段。随着系统规模扩大与运行复杂度提升,如何对光伏、储能、负荷等流进行实时调控,成为智慧用能的关键。ACCU100微…...

数据通信与计算机网络——数字传输
主要内容 数字到数字转换 线路编码 线路编码方案 块编码 扰动 模拟到数字转换 脉冲码调制(PCM) Delta调制(DM) 传输模式 并行传输 串行传输 一、数字到数字转换 将数字数据转换为数字信号涉及三种技术: 线…...
Java方法引用深度解析:从匿名内部类到函数式编程的演进
文章目录 前言问题场景第一种:传统的匿名内部类技术解析优缺点分析 第二种:Lambda表达式的革命技术解析Lambda表达式的本质性能优势 第三种:方法引用的极致简洁技术解析 方法引用的四种类型1. 静态方法引用2. 实例方法引用3. 特定类型的任意对…...
SparkSQL 优化实操
一、基础优化配置 1. 资源配置优化 # 提交Spark作业时的资源配置示例 spark-submit \--master yarn \--executor-memory 8G \--executor-cores 4 \--num-executors 10 \--conf spark.sql.shuffle.partitions200 \your_spark_app.py 参数说明: executor-memory: 每…...
力扣刷题(第四十九天)
灵感来源 - 保持更新,努力学习 - python脚本学习 反转链表 解题思路 迭代法:通过遍历链表,逐个改变节点的指针方向。具体步骤如下: 使用三个指针:prev(初始为None)、curr(初始为…...
03 Deep learning神经网络的编程基础 代价函数(Cost function)--吴恩达
深度学习中的损失函数(Cost Function)用于量化模型预测与真实数据的差距,是优化神经网络的核心指标。以下是常见类型及数学表达: 核心原理 逻辑回归通过sigmoid函数将线性预测结果转换为概率: y ^ ( i ) \hat{y}^{(i)}...
PHP:Web 开发的强大基石与未来展望
在当今数字化时代,Web 开发技术日新月异,各种编程语言和框架层出不穷。然而,PHP 作为一种历史悠久且广泛应用的服务器端脚本语言,依然在 Web 开发领域占据着重要地位。 PHP 的历史与现状 PHP(Hypertext Preprocessor…...
【Linux】为 Git 设置 Commit 提交模板方法,可统一个人或者项目的提交风格
为 Git 设置 Commit 提交模板 新建模板文件。注意之后不能删除该文件。 gedit ~/.gitmessage.txt粘贴自己的模板。可以给 AI 提自己的需求,定制一个模板,例如 # <type>(<scope>): <description> # # [optional body] # # [optional…...

【办公类-104-01】20250606通义万相50分一天用完,通义万相2.1专业版测试
背景需求: 昨天打开通义万相,发现分数降低到3位数,原来时1500.仔细看,原来每天的50分,只有1天有效期了。 用掉试试,用的是之前的30天积分,还是今天的1天积分 纯白色背景,卡通简笔画…...

中医的十问歌和脉象分类
中医核心理论框架如下 诊断技术如下 本文主要介绍问诊和切诊。 十问歌的“十”是虚指,实际包含12个核心问题,脉象28种中常见仅10余种,重点解释脉诊的物理本质(血流动力学触觉感知) 以下是中医十问歌的完整内容及脉…...