使用单个查询的MySQL多对多交集

时间:2013-11-23 11:31:30

标签: mysql sql

我有三张桌子:

People (pk: ID_PERSON)
Employees (pk: ID_EMPLOYEE)
Meetings (pk: ID_MEETING, fk: ID_PERSON, fk: ID_EMPLOYEE)

我需要根据以下条件从会议中选择人员:“找到遇到Employee1 AND Employee2的所有人”

如果我只想选择一个Employee进行过滤,那么我会执行以下操作:

SELECT ID_PERSON FROM Meetings
WHERE ID_EMPLOYEE=:Employee1

但选择至少遇到两个人的人最有效的方法是什么?我可以想象这样的事情:

SELECT
    ID_PERSON
FROM
    Meetings
WHERE
    ID_EMPLOYEE=:Employee2
AND ID_PERSON IN
    (SELECT ID_PERSON FROM Meetings
     WHERE ID_EMPLOYEE=:Employee1)

但子查询可能会返回大量记录。有没有更好的方法?是否存在单个查询解决方案?

2 个答案:

答案 0 :(得分:1)

可以使用自联接完成。为避免重复,您可以使用distinct。

SELECT
    DISTINCT(m1.ID_PERSON)
FROM
    Meetings m1, Meetings m2
WHERE
    m1.ID_EMPLOYEE=:Employee2
AND
    m2.ID_EMPLOYEE=:Employee1
AND
    m1.ID_PERSON = m2.ID_PERSON

答案 1 :(得分:1)

这个(常见)问题有各种解决方案。它可以使用EXISTS子查询来解决:

SELECT
    p.id_person
FROM
    People AS p
WHERE
    EXISTS ( SELECT 1 
             FROM Meetings AS m 
             WHERE m.id_person = p.id_person
               AND m.id_employee = :Employee1) 
  AND 
    EXISTS ( SELECT 1
             FROM Meetings AS m 
             WHERE m.id_person = p.id_person
               AND m.id_employee = :Employee2
           ) ;

...或多个JOINMeetings表。 (我假设)一个人可以与员工进行多次会面,因此如果您使用联接,则必须有DISTINCTGROUP BY(如@ popovitsj的回答)

另一种解决方案是拥有GROUP BYCOUNT()。查询更紧凑,但效率通常较低:

SELECT
    id_person
FROM
    Meetings AS m 
WHERE
    id_employee IN (:Employee1, :Employee2)
GROUP BY 
    id_person 
HAVING
    COUNT( DISTINCT id_employee ) = 2 ;