2014-09-25 71 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