SQL问题。在一张桌子上找到两个爱好相同的人

时间:2018-09-24 18:57:41

标签: mysql sql

表[tbl_hobby]

person_id(int),hobby_id(int)

有很多记录。我想获取一个SQL查询,以查找所有具有相同爱好(相同hobby_id)的人对。

如果A的hobby_id为1,则B也是如此;如果A的hobby_id为2,B也没有,那么我们将输出A&B的person_id。

如果A和B以及C达到极限,我们将输出A&B,B&C,A&C。

我已经完成了一个非常非常愚蠢的方法,多次联接表本身和多个子查询。当然要受到领导的嘲笑。

SQL中是否存在针对此问题的高性能方法?

从36个小时前开始,我为此一直在努力思考……


mysql转储中的示例数据

CREATE TABLE `tbl_hobby` (
  `person_id` int(11) NOT NULL,
  `hobby_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `tbl_hobby` (`person_id`, `hobby_id`) VALUES
(1, 1),(1, 2),(1, 3),(1, 4),(1, 5),(2, 2),
(2, 3),(2, 4),(3, 1),(3, 2),(3, 3),(3, 4),
(4, 1),(4, 3),(4, 4),(5, 1),(5, 5),(5, 9),
(6, 2),(6, 3),(6, 4),(7, 1),(7, 3),(7, 7),
(8, 2),(8, 3),(8, 4),(9, 1),(9, 2),(9, 3),
(9, 4),(10, 1),(10, 5),(10, 9),(10, 11);
COMMIT;

专家结果:(2和6和8相同,3和9相同)

2,6
2,8
6,8
3,9

结果记录的顺序和一个记录中两个数字的顺序并不重要。一栏或两栏的结果记录都可以接受,因为可以很容易地将其记录或分隔。

2 个答案:

答案 0 :(得分:4)

每人总计以获取自己的兴趣爱好。然后,按爱好列表汇总,找出属于多个人的人。

select hobbies, group_concat(person_id order by person_id) as persons
from
(
  select person_id, group_concat(hobby_id order by hobby_id) as hobbies
  from tbl_hobby
  group by person_id
) persons
group by hobbies
having count(*) > 1
order by hobbies;

这给出了每个爱好的人员列表。这是输出解决方案的最简单方法,否则我们将不得不构建所有可能的对。

更新:如果要配对,则必须查询该表两次:

select p1.person_id as person 1, p2.person_id as person2
from
(
  select person_id, group_concat(hobby_id order by hobby_id) as hobbies
  from tbl_hobby
  group by person_id
) p1
join
(
  select person_id, group_concat(hobby_id order by hobby_id) as hobbies
  from tbl_hobby
  group by person_id
) p2 on p2.person_id > p1.person_id and p2.hobbies = p1.hobbies
order by person1, person2;

答案 1 :(得分:1)

替代版本,不使用任何专有字符串处理:

select distinct t1.person_id, t2.person_id
from tbl_hobby t1
join tbl_hobby t2
  on t1.person_id < t2.person_id
where 2 = all (select count(*)
               from tbl_hobby 
               where person_id in (t1.person_id, t2.person_id)
               group by hobby_id);

也许效率较低,但可移植!