面试题答案
一键面试简单查询分析
简单查询难以解决此问题。简单查询通常适用于单表操作或多表简单关联获取直接数据。而本题需求涉及多表复杂关联(用户表、关系表、动态表),要获取每个用户及其关注用户的最新动态,还需按发布时间倒序并限制数量,简单查询无法满足这种复杂逻辑。
复杂查询设计
以MySQL为例:
WITH UserFollowedPosts AS (
SELECT
r.follower_id,
p.post_id,
p.user_id,
p.post_time,
p.post_content
FROM
relationships r
JOIN
posts p ON r.followed_id = p.user_id
UNION ALL
SELECT
u.user_id AS follower_id,
p.post_id,
p.user_id,
p.post_time,
p.post_content
FROM
users u
JOIN
posts p ON u.user_id = p.user_id
)
SELECT
uf.follower_id,
uf.post_id,
uf.user_id,
uf.post_time,
uf.post_content
FROM (
SELECT
follower_id,
post_id,
user_id,
post_time,
post_content,
ROW_NUMBER() OVER (PARTITION BY follower_id ORDER BY post_time DESC) AS rn
FROM
UserFollowedPosts
) uf
WHERE
uf.rn <= 5
ORDER BY
uf.follower_id, uf.post_time DESC;
关键技术及性能影响
- CTE(Common Table Expression,公用表表达式):
- 关键作用:通过
WITH UserFollowedPosts AS (...)
定义了一个临时表UserFollowedPosts
,它结合了用户自身发布的动态以及其关注用户发布的动态。使得复杂查询逻辑可以模块化,提高了查询的可读性和可维护性。 - 性能影响:在计算CTE时,数据库会将其结果集缓存起来,如果后续多次引用该CTE,不会重复计算,在一定程度上提高了效率。但如果CTE生成的结果集非常大,会占用较多的内存或临时存储,可能影响整体性能。
- 关键作用:通过
- UNION ALL:
- 关键作用:用于合并用户自身发布动态的结果集和其关注用户发布动态的结果集。
UNION ALL
不会去重,保留所有记录,满足本题获取所有相关动态的需求。 - 性能影响:相比
UNION
(会去重),UNION ALL
性能更好,因为它无需进行额外的去重操作。但如果存在大量重复记录,会增加后续处理的数据量,对内存和处理时间有一定影响。
- 关键作用:用于合并用户自身发布动态的结果集和其关注用户发布动态的结果集。
- 窗口函数(ROW_NUMBER()):
- 关键作用:
ROW_NUMBER() OVER (PARTITION BY follower_id ORDER BY post_time DESC)
根据follower_id
分区,在每个分区内按post_time
倒序为每条记录生成一个唯一的行号。通过这种方式,可以方便地筛选出每个用户(follower_id
)对应的最新5条动态。 - 性能影响:窗口函数的计算依赖于整个分区的数据,当数据量较大时,计算成本较高。但合理使用窗口函数可以避免复杂的自连接操作,在某些情况下整体性能可能优于其他方法。
- 关键作用:
- 子查询和过滤条件:
- 关键作用:最外层子查询中
WHERE uf.rn <= 5
用于筛选出每个用户对应的最新5条动态,ORDER BY uf.follower_id, uf.post_time DESC
按用户ID和动态发布时间倒序排列最终结果。 - 性能影响:合理的过滤条件可以减少最终返回的数据量,提高查询性能。但如果过滤条件不合理,如使用函数操作列,可能导致索引无法使用,从而降低查询效率。
- 关键作用:最外层子查询中