桌子[待定爱好]
个人id(int)、爱好id(int)
有很多记录。我想得到一个SQL查询来查找所有具有相同爱好(相同爱好id)的人。
如果A有爱好1,B也有,如果A没有爱好2,B也没有,我们将输出A&B的个人id。
如果A、B、C达到极限,我们输出A、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
结果记录的顺序和一条记录中两个数字的顺序并不重要。一列或两列的结果记录都可以接受,因为它可以很容易地浓缩或分离。
最佳答案
把每个人的爱好加起来。然后按爱好列表汇总,找出哪些属于多个人。
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;