我的PieCloudDB数据库中有两个表,一个表记录用户的朋友关系,另一个表记录用户最喜欢的页面ID.

user1_id user2_id
1 2
1 3
2 5
3 4
4 6
5 3
6 1
user_id page_id
1 28
2 66
3 5
3 49
4 32
5 8
6 28
6 49

如果一个页面被用户的至少一个朋友喜欢,但用户自己不喜欢,那么该页面将被推荐给该用户.

现在我需要一个解决方案来 for each 用户找到所有可能的页面推荐.

示例数据的结果应为:

user_id page_id likes_numbers
1 5 1
1 49 2
1 66 1
2 8 1
2 28 1
3 8 1
3 28 1
3 32 1
4 5 1
4 28 1
4 49 2
5 5 1
5 49 1
5 66 1
6 32 1

用户1是用户2、3和6的好友. 推荐页面为5个(用户3点赞),49个(both个用户3和6个用户点赞),66个(用户2点赞). 请注意,不推荐第28页,因为用户1已经喜欢它了.

likes_numbers表示喜欢这个页面的朋友数量.

下面是我的查询,我可以得到正确的答案,但执行时间太长(特别是当数据变得更大时).我想做得更好,有人能给我一些建议吗?

SELECT DISTINCT f.user1_id AS user_id, l.page_id, COUNT(*) AS likes_numbers
FROM (
    SELECT user1_id, user2_id
    FROM Friendship
    UNION
    SELECT user2_id, user1_id
    FROM Friendship
) f
JOIN likes l ON f.user2_id = l.user_id
WHERE f.user1_id NOT IN (SELECT user_id FROM likes WHERE user_id = f.user1_id AND page_id = l.page_id)
GROUP BY f.user1_id, l.page_id

推荐答案

您可以使用NOT EXISTS,如下所示:

SELECT f.user1_id AS user_id, l.page_id, COUNT(*) AS likes_numbers
FROM (
    SELECT user1_id, user2_id
    FROM Friendship
    UNION
    SELECT user2_id, user1_id
    FROM Friendship
) f
JOIN likes l ON f.user2_id = l.user_id
WHERE NOT EXISTS (SELECT 1 
                    FROM likes lK 
                   WHERE f.user1_id = LK.user_id AND LK.page_id = l.page_id)
GROUP BY f.user1_id, l.page_id;

或者,您也可以 Select 使用LEFT JOIN,如下所示:

SELECT f.user1_id AS user_id, l.page_id, COUNT(*) AS likes_numbers
FROM (
    SELECT user1_id, user2_id
    FROM Friendship
    UNION
    SELECT user2_id, user1_id
    FROM Friendship
) f
JOIN likes l ON f.user2_id = l.user_id
LEFT JOIN likes lK ON f.user1_id = LK.user_id AND LK.page_id = l.page_id
WHERE LK.user_id IS NULL
GROUP BY f.user1_id, l.page_id;

Sql相关问答推荐

SQL:创建查询以添加减少的总数

基于列对多行求和的查询

如何更改函数返回的列名?

SQL查询视图与连接?

在Oracle SQL中将列值转换为行

每年独特口味的冰淇淋数量

找到最新的连线

Oracle分层查询-两条路径在末尾合并为一条

按属性值 Select 数组元素Postgres Jsonb

按两列分组,并根据SQL中的条件返回第三个列值

如何使子查询在UPDATE语句期间获得最新更新

需要使用SQLite查询进行一些奇怪的时间转换

VS代码无法识别SQL代码中带括号的字符串

Select 组中的第一行,但在并发环境中

Oracle 21c 中的递归查询回顾过go 3 周

为 sqlite 全文搜索 (fts) 创建触发器时出现虚拟表的不安全使用

根据条件列出不同的值

PlSql 陷入死循环

交叉应用 OPENJSON / PIVOT - 错误的顺序

在 sql 中合并系列以删除重复项