2013-05-19 45 views
1

的MySQL 5.5MySQL如何找到確切的兒童組父母?

 
parent table: 
id | facts 
 
child table: 
parent_id | foreign_key | facts 

現在,我想找到具有一定的確切集合的孩子,沒有更多,不會少的父母。像這樣:

SELECT t1.`id` 
from `parent_table` t1 
    LEFT JOIN `child_table` t2 ON t1.id=t2.parent_id 
WHERE t2.`fk` = 1 
    AND t2.`fk` = 3 
    AND t2.`fk` = 5 
    AND t2.`fk` = 7 
    AND t2.`fk` = 9 

但是,這也將得到一個父記錄與這組兒童:1,2,3,5,7,9。我只想要那些有確切集合的父母:1,3,5,7,9。

有沒有辦法?

編輯: child.parent_id和child.fk是都不是唯一的。 child.fk是連接到另一個表的外鍵。 (「多對多關係」)因此,父母有可能生孩子1,2,3,5,7,9。我做這個查詢的全部原因是爲了避免爲1,3,5,7,9創建一個新的父項,如果這樣的父項已經存在的話。

回答

2

假設child.id對於每個child.parent_id都是唯一的。

SELECT a.id, a.facts 
FROM parent a 
     INNER JOIN child b 
      ON a.id = b.parent_ID 
WHERE b.id IN (1,3,5,7,9) AND  -- <<== list all ChildID here 
     EXISTS       -- <<== this part checks if the parent_ID 
     (        --   present on the EXISTS clause 
      SELECT parent_ID   --   which only filters parents 
      FROM child c   --   with 5 children 
      WHERE b.parent_ID = c.parent_ID 
      GROUP BY parent_ID 
      HAVING COUNT(*) = 5  -- <<== total number of children 
     ) 
GROUP BY a.id, a.facts 
HAVING COUNT(*) = 5     -- <<== total number of children 
+0

我認爲依靠自己的計數是不可靠的。 eggyal的解決方案看起來更強大,因爲它也檢查NOT值。 –

+0

您爲什麼認爲'COUNT(*)'不可靠?我需要檢查「NOT」值嗎?嘗試運行腳本並查看結果而不檢查「NOT」值。 –

+0

它似乎沒有工作。在這裏檢查我更新的小提琴,以使用您的查詢與更新的模式:http://www.sqlfiddle.com/#!2/d8e2a/5 –

1
SELECT parent_id 
FROM  child_table 
GROUP BY parent_id 
HAVING SUM(id IN (1,3,5,7,9)) = COUNT(*) 
    AND COUNT(DISTINCT id) = 5 
+0

這看起來很有趣。 –

+0

我修改了一下我的問題。 'child'表是一個連接表,不是'id',它應該是'fk'。 'fk'當然可以有重複。對不起,如果這是令人困惑。 –

+0

@ButtleButkus我們的意思是一個複合獨特的列。 'UNIQUE(parent_ID,child_ID)'而不是'UNIQUE(Parent_ID)和UNIQUE(Child_ID)'。兩者都不同。 –

1

這個問題被稱爲(精確)關係分裂。本文中有很多有用的代碼和解釋:Divided We Stand: The SQL of Relational Division

一種方法來解決這個問題:

SELECT p.id AS parent_id 
FROM parent AS p 
WHERE EXISTS 
     (SELECT * FROM child AS c 
     WHERE c.fk = 1 AND c.parent_id = p.id) 
    AND EXISTS 
     (SELECT * FROM child AS c 
     WHERE c.fk = 3 AND c.parent_id = p.id) 
    AND EXISTS 
     (SELECT * FROM child AS c 
     WHERE c.fk = 5 AND c.parent_id = p.id) 
    AND EXISTS 
     (SELECT * FROM child AS c 
     WHERE c.fk = 7 AND c.parent_id = p.id) 
    AND EXISTS 
     (SELECT * FROM child AS c 
     WHERE c.fk = 9 AND c.parent_id = p.id) 
    AND NOT EXISTS 
     (SELECT * FROM child AS c 
     WHERE c.fk NOT IN (1,3,5,7,9) AND c.parent_id = p.id) ; 

而在StackOverflow上,另一個鏈接到一個類似的問題,在這裏,你會發現超過10級不同的解決方案(注:這是不是確切的劃分,但對於與餘數師)和性能測試(Postgres的):How to filter SQL results in a has-many-through relation

+0

您沒有定義表格別名「c」 –

+0

不是嗎?我正在閱讀'FROM child AS c' –

+0

哦,你的確的確如此。這可行,但我希望可能更像eggyal的解決方案的工作,因爲它更短,並不涉及潛在的幾十個子查詢。 –

1

類似eggyal的解決方案,只是想我會在把它作爲一種替代,因爲它應該是更輕便跨RDBMS的;

SELECT c.parent_id 
FROM child_table c 
GROUP BY c.parent_id 
HAVING SUM(CASE WHEN c.id IN (1,3,5,7,9) THEN 1 ELSE -1 END) = 5 

5是你想匹配IN子句中的孩子的確切數量(在這種情況下,所有)

這將僅具有鮮明的孩子工作,如果有重複,這將打破。

An SQLfiddle to test with

+0

MySQL沒有'EXCEPT'(只有Postgres,DB2和SQL-Server和Oracle作爲'MINUS'。) –

+0

@ypercube * doh *嘗試在數據庫之間切換,並最終在SQL服務器上測試:)刪除,直到我修復它... ... –

+0

@ypercube:Oracle也有它(在那裏稱爲'MINUS'),DB2也是如此(還有其他幾個例如Derby,H2,...) –