2012-02-22 175 views
1

我有一個名爲'members'的數據庫表。分配給成員是positionMySQL:不包含

Positions來自Departments。我有Departments,然後Sub-Departments在子部門內的職位和職位。

希望我沒有失去你。

我想要做的是選擇一個部門內的所有成員,但不包括該部門內某個職位的任何成員。

「部門」 表(包括部門和分部門)

ID  NAME     PARENT_ID 
1  Department #1   NULL 
2  Department #2   NULL 
3  Sub Department #1  1  
4  Sub Department #2  1  
5  Sub Department #3  2 

「departments_positions」 表:

ID  NAME    SUB_DEPARTMENT_ID 
1  Position #1  3 
2  Position #2  3 
3  Position #3  4  

「members_positions」 表:

ID  MEMBER_ID  POSITION_ID 
1  1    1 
2  1    2 
3  1    3   

這裏是我的MySQL代碼:

SELECT m.* FROM members AS m 
    LEFT JOIN members_positions AS mp ON mp.member_id = m.id 
    LEFT JOIN departments_positions AS dp ON mp.position_id = dp.id 
    LEFT JOIN departments AS sd ON dp.sub_department_id = sd.id 
    LEFT JOIN departments AS d ON sd.parent_id = d.id 
    WHERE mp.position_id != '2' AND d.id = '1' 
    GROUP BY m.id 

因此,您可以看到我想提取「Department#1」(ID:1來自departments_table)中的成員,但不是位於#2的位置#2(ID:2 from departments_positions表)中的成員部。

希望我有道理。我上面的代碼似乎不起作用。它只是從部門出口每個人。

回答

3

這是因爲您使用的是LEFT JOIN,它不會過濾數據。

更改您的查詢以使用INNER JOIN。

如果您是按成員標識分組,您也不能使用select *。

編輯:我輸入您的表到本地的MySQL數據庫,並確認此查詢工作。

​​

而且,任何理由爲什麼你引述的國際價值在哪裏聲明2 & 1?

如果你只想要唯一的成員id,你不需要做一個GROUP BY。你應該切換您選擇這個,然後使用一個外選擇讓所有的成員信息:

SELECT m.* 
FROM members m 
INNER JOIN (
    SELECT DISTINCT mp.member_id 
    ... the rest... 
) innerQ ON innerQ.member_id = m.id 
+0

我沒有忽略它,你有SELECT DISTINCT從你從整個成員表中選擇的點和SELECT DISTINCTING整個表。我建議把它做到上面的級別,以便只有當你知道你想要哪些行能夠由PK單獨訪問時,才能訪問成員。即使有你的補充,我們的答案也不相同,並且我確信我建議在負載下證明是最佳的。另外我建議不要加入部門。 – 2012-02-23 00:48:07

+0

@ Simonatmso.net我不是在爭論不必要的加入,也不是,我沒有從整個會員表中挑選。僅在所有示例中選擇了成員標識。 – Timeout 2012-02-23 00:58:50

2

我寧願避免GROUP BY和潛在的大量加入可能時這樣會看看下面的

SELECT m.* 
FROM members AS m 
INNER JOIN (
    SELECT DISTINCT mp.member_id 
    FROM members_positions AS mp 
    INNER JOIN departments_positions AS dp 
     ON dp.id = mp.position_id 
     AND dp.id != 2 
    INNER JOIN departments AS sd 
     ON sd.id = dp.sub_department_id 
     AND sd.parent_id = 1 
) AS validMembers 
ON validMembers.member_id = m.id 

首先,你不需要加入departments兩次。這是因爲您加入sd.parent_id = d.id,然後將其限制爲d.id = 1。你可以壓縮這些,然後刪除join, giving sd.parent_id = 1`。

現在向下移動一點,INNER JOIN達到member_positions, restrict it to instances where mp.position_id!= 2 and select the DISTINCT mp.member_id`。到目前爲止,這些都是很簡單的連接,只需要最少的數據。

最後這個名單加入到成員,所以現在從成員提供檢索數據只對那些你感興趣的行。

爲了進一步提高本以下索引的速度(在這一領域的順序)可能是有益的(假設它們當然不存在)。

member_positions INDEX (position_id, member_id) 
department_positions INDEX (sub_department_id) -- assumes id is the PK 
departments INDEX (parent_id) -- assumes id is the PK