SQL选择多对多

时间:2014-09-25 23:32:48

标签: mysql join many-to-many

我使用的是MYSQL 5.X,我在查找查询时遇到了麻烦;

我有两个有多对多关系的实体。

客户端和服务,因此我有3个表:

客户端,clients_has_services和服务。

我需要选择与特定客户无关的每项服务。

例如: 我的客户端ID为1,总共有4个服务(Service1,Service2,Service3,Service4),客户端1与Service1有关系)所以我需要检索所有其他服务(Service2,Service3,Service4)

建议?

2 个答案:

答案 0 :(得分:1)

首先,获取一个全部services

将其加入clients对于"特定客户端"的行,以便为客户端提供一组所有服务。

"技巧"是使用反连接模式来排除你所拥有的行#34;匹配"在clients_have_services表中。

如果您拥有客户端的唯一标识符(并且您只需要单个客户端的列表),请执行以下操作:

SELECT s.*
  FROM services s
  LEFT
  JOIN clients_have_services h
    ON h.service_id = s.id
   AND h.client_id = 42
 WHERE h.service_id IS NULL
 ORDER BY s.id

外部联接返回services的所有行,以及任何"匹配"来自clients_have_services表的行。 "技巧"是WHERE子句中的谓词,排除找到匹配项的任何行,只留下与特定客户端无关的services

如果您为多个客户端执行此操作...您还需要返回与服务交叉连接的客户端(作为客户端和服务的交叉产品),然后排除匹配项。

例如:

SELECT c.id AS client_id
     , s.*
  FROM clients c
 CROSS 
  JOIN services s
  LEFT
  JOIN clients_have_services h
    ON h.service_id = s.id
   AND h.client_id = c.id
 WHERE h.service_id IS NULL
 ORDER BY c.id, s.id

还有一些其他查询模式会返回相同的结果,例如NOT EXISTS

SELECT s.*
  FROM services s
 WHERE NOT EXISTS 
       ( SELECT 1
           FROM clients_have_services h
          WHERE c.client_id = 42
            AND h.service_id = s.id
       )
 ORDER BY s.id

答案 1 :(得分:1)

假设你的client_has_services纠正了多对多,所以你在双方都有一对多,所以你的client_has_services应该有: ID(密钥),Client_ID,Service_ID

SELECT * FROM services WHERE services.id != ANY (select client_has_services.services_id from client_has_services where client_has_services.client_id = ID_num_provided)