2012-02-22 2 views
1

データベーステーブル「members」があります。メンバーに割り当てられるのはpositionです。MySQL:除外

PositionsDepartmentsから来ています。私はDepartments、次にSub-Departmentsとそれらの部署内の位置を持っています。

うまくいけば私はあなたを失っていません。

私がしたいことは、部門内のすべてのメンバーを選択し、その部門内の1つの職位からそのメンバーを除外することです。 (部門やサブ部門を含んでいる)

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」(departments_tableからID:1)にあるメンバーを抽出したいのですが、Position#2(departments_positionsテーブルのID:2)のメンバーは抽出しません。部門。

うまくいけば私は理にかなっています。上記の私のコードは動作していないようです。部門から全員をエクスポートするだけです。

答えて

3

LEFT JOINを使用しているのは、データをフィルタリングしないためです。

INNER JOINを使用するようにクエリを変更します。

メンバーIDでグループ化する場合は、選択*を使用することもできません。

編集:あなたのテーブルをローカルのmysqlデータベースに入力し、このクエリの動作を確認しました。

​​

また、あなたはint型を引用していない理由はどこ文で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だけでアクセスできることがわかったら、アクセスしてください。あなたの追加でも、私たちの答えは同じではなく、私は負荷の下で最適であることを示唆していると私は確信しています。また、私は自分自身に学科に参加しないことを提案しました。 –

+0

@ Simonatmso.net私は不必要な参加に異議を唱えていませんでした。いいえ、私はメンバーテーブル全体から選択していませんでした。すべての例でメンバーIDのみを選択していました。 – Timeout

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に2度参加する必要はありません。これは、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 
関連する問題