原题和数据
friend表,userid是好友关系发起方,touserid是好友关系接受方.
这个问题比较普遍
用数据库处理的优点:
1.面向集合的处理方式,可以一次生成所有用户的数据,作为一段时间的缓存.
2.方案简单
缺点:
时间比较长.一般作为夜间维护作业.如果数据量特别大,超过了夜维的窗口,就需要改方案.
需求一:找任意两个人的共同好友
使用笛卡尔积
t1表的好友等于t2表的好友,并且不等于自己
这个结果是 t1的userid和t2的userid有共同好友.
最后聚合,求出 t1.userid和t2.userid的共同好友数量.
需求二:推荐可能认识的人
关于需求二有两种实现方式:
第一种,在需求一的基础上,将t2.userid是t1.userid好友的记录过滤.
第二种实现,找到每个人所有好友的好友,如果不是他的好友,则推荐.
where t1.userid!=t2.touserid
这句话是为了过滤已经建立好友关系的情况.
如果好友的好友,就是我自己,则过滤.
这两种实现,还是有差别的
第一种实现方式的语义是,若有人加过我的好友,但是没有加我,则推荐给我.
第二种实现方式的语义是,我好友加的好友,如果我没有加,则推荐给我
因为好友关系是双向的,单方面的请求,对方未必已经同意.
当然,可以进一步过滤,只保留建立了双向好友关系的记录,但是会进一步降低性能.似乎也没有这个必要.
从避免骚扰的角度考虑,选择第二种实现方式似乎较好.
- create table friend
- (
- userid varchar(10),
- touserid varchar(10)
- );
- insert into friend values('A','B');
- insert into friend values('A','C');
- insert into friend values('A','D');
- insert into friend values('A','E');
- insert into friend values('A','F');
- insert into friend values('A','O');
- insert into friend values('B','A');
- insert into friend values('B','C');
- insert into friend values('B','E');
- insert into friend values('B','K');
- insert into friend values('C','A');
- insert into friend values('C','D');
- insert into friend values('C','I');
- insert into friend values('C','F');
- insert into friend values('D','B');
- insert into friend values('D','C');
- insert into friend values('D','D');
- insert into friend values('D','M');
- insert into friend values('D','L');
- insert into friend values('E','B');
- insert into friend values('E','C');
- insert into friend values('E','D');
- insert into friend values('E','M');
- insert into friend values('E','L');
- insert into friend values('F','A');
- insert into friend values('F','B');
- insert into friend values('F','C');
- insert into friend values('F','D');
- insert into friend values('F','E');
- insert into friend values('F','O');
- insert into friend values('F','M');
- insert into friend values('G','A');
- insert into friend values('G','C');
- insert into friend values('G','D');
- insert into friend values('G','E');
- insert into friend values('G','F');
- insert into friend values('H','A');
- insert into friend values('H','C');
- insert into friend values('H','D');
- insert into friend values('H','E');
- insert into friend values('H','O');
- insert into friend values('I','A');
- insert into friend values('I','O');
- insert into friend values('J','A');
- insert into friend values('J','C');
- insert into friend values('J','D');
- insert into friend values('K','D');
- insert into friend values('K','E');
- insert into friend values('K','F');
- insert into friend values('L','D');
- insert into friend values('L','E');
- insert into friend values('L','F');
- insert into friend values('M','E');
- insert into friend values('M','F');
- insert into friend values('M','G');
- insert into friend values('O','A');
- insert into friend values('O','H');
- insert into friend values('O','I');
- insert into friend values('O','J');
friend表,userid是好友关系发起方,touserid是好友关系接受方.
这个问题比较普遍
用数据库处理的优点:
1.面向集合的处理方式,可以一次生成所有用户的数据,作为一段时间的缓存.
2.方案简单
缺点:
时间比较长.一般作为夜间维护作业.如果数据量特别大,超过了夜维的窗口,就需要改方案.
需求一:找任意两个人的共同好友
- select t1.userid,t2.userid,count(*) from friend t1,friend t2
- where
- t1.userid!=t2.userid and
- t1.touserid=t2.touserid
- group by t1.userid,t2.userid
- order by t1.userid,count(*) desc;
使用笛卡尔积
t1表的好友等于t2表的好友,并且不等于自己
这个结果是 t1的userid和t2的userid有共同好友.
最后聚合,求出 t1.userid和t2.userid的共同好友数量.
需求二:推荐可能认识的人
关于需求二有两种实现方式:
第一种,在需求一的基础上,将t2.userid是t1.userid好友的记录过滤.
- select t3.* from (
- select t1.userid source_userid,t2.userid target_userid,count(*) c from friend t1,friend t2
- where
- t1.userid!=t2.userid and
- t1.touserid=t2.touserid
- group by t1.userid,t2.userid
- ) t3 left join friend t4 on (t3.source_userid=t4.userid and t3.target_userid=t4.touserid)
- where t4.userid is null
- order by t3.source_userid,t3.c desc;
第二种实现,找到每个人所有好友的好友,如果不是他的好友,则推荐.
- select t3.* from (
- select t1.userid,t2.touserid,count(*) c
- from
- friend t1 inner join friend t2 on(t1.touserid=t2.userid)
- where t1.userid!=t2.touserid
- group by t1.userid,t2.touserid
- ) t3 left join friend t4 on (t3.userid=t4.userid and t4.touserid=t3.touserid)
- where t4.userid is null
- order by t3.userid,c desc;
where t1.userid!=t2.touserid
这句话是为了过滤已经建立好友关系的情况.
如果好友的好友,就是我自己,则过滤.
这两种实现,还是有差别的
第一种实现方式的语义是,若有人加过我的好友,但是没有加我,则推荐给我.
第二种实现方式的语义是,我好友加的好友,如果我没有加,则推荐给我
因为好友关系是双向的,单方面的请求,对方未必已经同意.
当然,可以进一步过滤,只保留建立了双向好友关系的记录,但是会进一步降低性能.似乎也没有这个必要.
从避免骚扰的角度考虑,选择第二种实现方式似乎较好.
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29254281/viewspace-1870745/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/29254281/viewspace-1870745/