2014-09-25 63 views
0

我正在使用MYSQL 5.X,并且在计算查询时遇到了问题;SQL选择多对多

我有2对多关系的实体。

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

客户,clients_has_services和服务。

我需要选择每个与特定客户端无关的服务。我的客户端ID为1,服务总数为4(服务1,服务2,服务3,服务4),客户端1与服务1有关系),所以我需要检索所有其他服务(服务2,服务3(服务3,服务3) ,Service4)

建议?

回答

1

首先,得到一组全部services

加入到“特定客户端”的clients行,以便为客户端提供一组所有服务。

“技巧”是使用反连接模式排除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 
+0

你回答的工作,,但你和 – 2014-09-25 23:45:01

+0

这是一个错字后输入“n”的而不是“H”。 (在我看来,An n看起来很像h(至少查询会返回一个错误,而不是错误的结果。) – spencer7593 2014-09-25 23:48:32

+0

ya,ty解释:D竖起大拇指! – 2014-09-25 23:51:46

1

假设你client_has_services矫正多对多,所以你在双方都有一对多的关系,所以你的client_has_services应该有: ID(Key),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)

+0

这个查询不会抛出一个子查询返回多行时出错?也许如果'!!='不等式比较被替换为'NOT IN'运算符,并且我们保证子查询不返回NULL值,这将起作用。 – spencer7593 2014-09-25 23:52:08

+0

如果它返回多行,它不是问题。它将为每个返回的行重新运行“superquery”。似乎不直观,但它的工作原理。 – Nick 2014-09-27 15:44:57

+0

您是否具有该行为的参考资料,或者是一个演示它的例子?我期望您的答案中的查询引发错误1242“子查询返回多于一行”。 [http://dev.mysql.com/doc/refman/5.5/en/subquery-errors.html](http://dev.mysql.com/doc/refman/5.5/en/subquery-errors.html) – spencer7593 2014-09-27 15:59:50