我有 2 張不同的桌子;第一個是“用戶”,第二個是“關系”。
用戶有“用戶名”列,關系有“用戶名”和“朋友名”。對于每個友誼實體,將向該表插入 2 行。例如,如果 John 將 Janna 添加為朋友,這意味著 John 也被 Janna 添加了。
我試圖找出像 Facebook 或 Twitter 中的朋友建議之類的東西。隨機用戶將從用戶表中選擇,并在關系表中檢查他們是否是朋友。這將持續進行,直到找到 5 個成功的非好友匹配并立即回傳(如果可能)。
我可以通過選擇所有行并自己在服務器中迭代/搜索來做到這一點,但我不認為這是 PostgreSQL 無法處理的事情。對于這個級別“相對”微不足道的功能,我的方式似乎太昂貴了。
有沒有什么簡單而優雅的方法來處理這個任務?
提前致謝,祝您周日/圣誕節之夜愉快。
更新:我正在附加一些模擬資料,抱歉延遲:
create table relations (
rel_id bigserial primary key not null ,
username VARCHAR(50) not null ,
friendname VARCHAR(50) not null ,
since DATE not null
);
insert into relations (rel_id, username, friendname, since) values (1,'user1', 'user2', '06/01/2021');
insert into relations (rel_id, username, friendname, since) values (2,'user2', 'user1', '06/01/2021');
insert into relations (rel_id, username, friendname, since) values (3,'user1', 'user3', '16/10/2021');
insert into relations (rel_id, username, friendname, since) values (4,'user3', 'user1', '16/10/2021');
insert into relations (rel_id, username, friendname, since) values (5,'user3', 'user5', '16/01/2020');
insert into relations (rel_id, username, friendname, since) values (6,'user5', 'user3', '16/01/2020');
create table Users (
user_id bigserial primary key not null ,
username VARCHAR(50) not null
);
insert into Users (user_id, username) values (1,'user1');
insert into Users (user_id, username) values (2,'user2');
insert into Users (user_id, username) values (3,'user3');
insert into Users (user_id, username) values (4,'user4');
insert into Users (user_id, username) values (5,'user5');
insert into Users (user_id, username) values (6,'user6');
insert into Users (user_id, username) values (7,'user7');
正如預期的結果查詢可能會建議 User4-5-6 和 7 給 User1 作為好友。因為根據表 user1 只有用戶 2 和用戶 3 是朋友。考慮到他不能與自己成為朋友,我們也不希望在結果中看到 user1。
uj5u.com熱心網友回復:
下一個選擇將準確回傳 5 個不是 John 的朋友的朋友名(在這種情況下)。必須應用第二個過濾器,以不為約翰回傳約翰。
SELECT DISTINCT(friendsname) FROM relations
WHERE username <> 'John' AND friendsname <> 'John'
LIMIT 5
要為此添加隨機因素,您可以通過以下方式修改選擇:
SELECT * FROM (
SELECT DISTINCT(friendsname) FROM relations
WHERE username <> 'John' AND friendsname <> 'John'
) as s
ORDER BY random()
LIMIT 5
請注意, random() 排序是一項繁重的操作,因為它執行掃描。
更新 要從用戶表而不是關系表中進行選擇,查詢可能如下所示:
SELECT * FROM users AS u
WHERE u.username NOT IN (SELECT friendname FROM relations WHERE username = 'user3') AND u.username <> 'user3'
ORDER BY random()
LIMIT 3
有兩個選擇沒有加入,只是過濾,它可能表現良好。我沒有在更大的桌子上測驗它。
uj5u.com熱心網友回復:
不使用游標,你可以做的一件事是通過交叉連接找到所有可能的友誼,然后洗掉現有的,最后選擇結果集的 5 個隨機行,就像這樣
select usernm, friend
from
(
select distinct greatest(a.username,b.username) usernm,least(a.username,b.username) friend
from users a
cross join users b
where a.username <> b.username
except
select distinct greatest(username, friendname) usernm, least(username, friendname) friend
from relations
) x
order by random() limit 5
最大和最小的用途是確保我們不會重復相同的友誼。交叉連接中的“where a.username <> b.username”也是為了不引入“自我友誼”。
資料庫小提琴:https : //www.db-fiddle.com/f/gpYMWHa2dK7BcZpxjHqwGa/0
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/395787.html
標籤:sql PostgreSQL的
