????????力扣1892,頁面推薦Ⅱ,為一個社交媒體網站實施一個頁面推薦系統。如果頁面被user_id
的?至少一個朋友喜歡?,而?不被user_id
喜歡?,你的系統將?推薦?一個頁面到user_id
。
目錄
題目描述
解題思路
完整代碼
優化
題目描述
表:?Friendship
+---------------+---------+ | Column Name | Type | +---------------+---------+ | user1_id | int | | user2_id | int | +---------------+---------+ (user1_id,user2_id) 是 Friendship 表的主鍵(具有唯一值的列的組合)。 該表的每一行表示用戶user1_id和user2_id是好友。
表:?Likes
+-------------+---------+ | Column Name | Type | +-------------+---------+ | user_id | int | | page_id | int | +-------------+---------+ (user_id,page_id) 是 Likes 表的主鍵(具有唯一值的列)。 該表的每一行表示user_id喜歡page_id。
您正在為一個社交媒體網站實施一個頁面推薦系統。如果頁面被user_id
的?至少一個朋友喜歡?,而?不被user_id
喜歡?,你的系統將?推薦?一個頁面到user_id
。
編寫一個解決方案來查找針對每個用戶的所有可能的?頁面建議?。每個建議應該在結果表中顯示為一行,包含以下列:
user_id
: 系統向其提出建議的用戶的ID。page_id
: 推薦為?user_id
?的頁面ID。.friends_likes
:??user_id
?對應?page_id
?的好友數。
以?任意順序?返回結果表。
返回結果格式示例如下。
示例 1:
輸入: Friendship 表: +----------+----------+ | user1_id | user2_id | +----------+----------+ | 1 | 2 | | 1 | 3 | | 1 | 4 | | 2 | 3 | | 2 | 4 | | 2 | 5 | | 6 | 1 | +----------+----------+ Likes 表: +---------+---------+ | user_id | page_id | +---------+---------+ | 1 | 88 | | 2 | 23 | | 3 | 24 | | 4 | 56 | | 5 | 11 | | 6 | 33 | | 2 | 77 | | 3 | 77 | | 6 | 88 | +---------+---------+ 輸出: +---------+---------+---------------+ | user_id | page_id | friends_likes | +---------+---------+---------------+ | 1 | 77 | 2 | | 1 | 23 | 1 | | 1 | 24 | 1 | | 1 | 56 | 1 | | 1 | 33 | 1 | | 2 | 24 | 1 | | 2 | 56 | 1 | | 2 | 11 | 1 | | 2 | 88 | 1 | | 3 | 88 | 1 | | 3 | 23 | 1 | | 4 | 88 | 1 | | 4 | 77 | 1 | | 4 | 23 | 1 | | 5 | 77 | 1 | | 5 | 23 | 1 | +---------+---------+---------------+ 解釋: 以用戶1為例: —用戶1是用戶2、3、4、6的好友。 -推薦頁面有23(用戶2喜歡),24(用戶3喜歡),56(用戶3喜歡),33(用戶6喜歡),77(用戶2和用戶3喜歡)。 -請注意,第88頁不推薦,因為用戶1已經喜歡它。另一個例子是用戶6: —用戶6是用戶1的好友。 -用戶1只喜歡了88頁,但用戶6已經喜歡了。因此,用戶6沒有推薦。您可以使用類似的過程為用戶2、3、4和5推薦頁面。
解題思路
????????這個問題可以通過結合兩個表(Friendship
和Likes
)來解決,目標是找到對每個用戶推薦的頁面。具體步驟如下:
- 確定朋友關系:首先,我們需要從
Friendship
表中識別每個用戶的所有朋友。由于朋友關系是雙向的(如果A是B的朋友,那么B也是A的朋友),我們需要考慮user1_id
和user2_id
兩個方向。 - 識別朋友喜歡的頁面:接下來,我們需要查找每個用戶的朋友喜歡哪些頁面。
- 排除用戶已經喜歡的頁面:我們需要確保推薦的頁面不包括用戶已經喜歡的頁面。
- 計算每個推薦頁面的朋友喜歡數:對于每個推薦的頁面,我們需要計算有多少個朋友喜歡它。
- 輸出結果:最后,我們需要按照題目要求輸出結果,包括
user_id
、page_id
和friends_likes
。
完整代碼
SELECT F.user_id,L.page_id,COUNT(*) AS friends_likes
FROM (SELECT user1_id AS user_id, user2_id AS friend_id FROM FriendshipUNION ALLSELECT user2_id, user1_id FROM Friendship
) AS F
JOIN Likes AS L ON F.friend_id = L.user_id
LEFT JOIN Likes AS UL ON F.user_id = UL.user_id AND L.page_id = UL.page_id
WHERE UL.user_id IS NULL
GROUP BY F.user_id, L.page_id
ORDER BY F.user_id, L.page_id;
- 朋友關系:通過
UNION ALL
將Friendship
表中的user1_id
和user2_id
合并,確保朋友關系的雙向性被考慮。 - 朋友喜歡的頁面:通過將上述結果與
Likes
表連接,找到每個用戶的朋友喜歡哪些頁面。 - 排除已喜歡的頁面:使用
LEFT JOIN
將用戶喜歡的頁面與朋友喜歡的頁面進行比較,通過WHERE UL.user_id IS NULL
條件排除用戶已經喜歡的頁面。 - 計算朋友喜歡數:通過
COUNT(*)
計算每個推薦頁面的朋友喜歡數。 - 輸出結果:最后,根據
user_id
和page_id
分組,按照題目要求輸出結果。
通過
優化
????????強調效率問題,其實在運行能力有限的情況下,討論優化SQL是十分必要的。盡量多用left/right join + where xx is null的形式來代替not in的表示形式。
with t1 as (select user1_id user_id,user2_id friend_idfrom Friendshipunion allselect user2_id user_id,user1_id friend_idfrom Friendship)
,t3 as (select t1.user_id,t1.friend_id ,t2.page_idfrom t1 left join Likes t2 on t1.friend_id = t2.user_id)
select t3.user_id,t3.page_id,count(1) friends_likes
from Likes t4
right join t3
on t4.user_id = t3.user_id
and t4.page_id = t3.page_id
where t4.page_id is null
group by 1,2