2011-12-18 64 views
1

因此在數據庫中有一個名爲roles_users的表。這包含用戶擁有的所有角色。這裏有兩列:user_id,role_id。SQL:Where IN查詢

一個普通用戶,沒有額外的角色,在這個表中有1行。此行有role_id 1.

管理員用戶,在此表中有2行。一個與ROLE_ID 1,和一排與ROLE_ID 2

像這樣:

user_id role_id 
88  1 
88  2 
99  1 // Only one row with that user_id, so he's a user 

現在我試着去統計有多少用戶/管理/銷售商/合作伙伴存在。

賣家有3行,一個帶ROLE_ID 1,ROLE_ID 2和3 ROLE_ID

合作伙伴已經ROLE_ID 1,ROLE_ID 4

所以我想這:

SELECT user_id FROM roles_users WHERE role_id IN (1) // MEMBERS ONLY 
SELECT user_id FROM roles_users WHERE role_id IN (1,2) // ADMIN 
SELECT user_id FROM roles_users WHERE role_id IN (1,2,3) // SELLER 
SELECT user_id FROM roles_users WHERE role_id IN (1,4) // PARTNERS 

但這些查詢不能正常工作。他們給我的數量超過了它的預期。我相信這是因爲它不排除任何行,

我的意思是在查詢時它應該查找role_id 1,對於成員,它也包括合作伙伴,管理員,賣家也是因爲它只檢查它是否是theres任何與行role_id 1和多數民衆贊成它。

那麼我該如何做到這一點?因此,當它看起來在成員之後,它也應該確保user_id沒有更多的行與其他role_id像2,3,4

+0

嘗試選擇不同的user_Id – Sparky 2011-12-18 20:27:12

+0

您需要的關係運算符是[division](http://en.wikipedia.org/wiki/Relational_algebra#Division_2.8.C3.B7.29),通常稱爲[「supplier」誰提供所有部件「](http://www.dbdebunk.com/page/page/772076.htm)。建議閱讀[這裏](http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/),[here](http: //www.dbdebunk.com/page/page/772076.htm)和[這裏](http://www.cs.arizona.edu/~mccann/research/divpresentation.pdf)。 – onedaywhen 2011-12-19 09:24:54

回答

0

這將給你所有的表中的權限組合與他們的計數

SELECT 
    COUNT(*) AS num 
    GROUP_CONCAT(role_id ORDER BY role_id) AS privilegeset 
FROM roles_users 
GROUP BY user_id 
+0

呃!這真的有用嗎?小心解釋這背後的邏輯? – fge 2011-12-18 20:55:16

0

關於銷售商和合作夥伴:
據我瞭解,賣方是可以擁有role_id = 3和合作夥伴,可以有role_id = 4,正確的唯一的唯一的?

如果是的話,找銷售商和合作夥伴是很容易的:

SELECT user_id FROM roles_users WHERE role_id = 3 // SELLER 
SELECT user_id FROM roles_users WHERE role_id = 4 // PARTNERS 
0

下面是一個基於連接的解決方案是希望可以在任何SQL。

SELECT user_id FROM roles_users RU0 
LEFT JOIN roles_users RU1 ON RU0.user_id = RU1.user_id AND RU1.role_id = 1 
LEFT JOIN roles_users RU2 ON RU0.user_id = RU2.user_id AND RU2.role_id = 2 
LEFT JOIN roles_users RU3 ON RU0.user_id = RU3.user_id AND RU3.role_id = 3 
LEFT JOIN roles_users RU4 ON RU0.user_id = RU4.user_id AND RU4.role_id = 4 
WHERE RU1.user_id IS NOT NULL -- should have role 1 
    AND RU2.user_id IS NULL  -- should NOT have role 2 
    AND RU3.user_id IS NULL  -- should NOT have role 3 
    AND RU4.user_id IS NOT NULL -- should have role 4 

只是改變where子句中的「IS NULL」和「IS NOT NULL」以更改您希望用戶擁有或不擁有的角色。

1

group_concat是你想要什麼:

select 
    case roles 
     when '1' then 'members' 
     when '1,2' then 'admins' 
     when '1,2,3' then 'sellers' 
     when '1,4' then 'partners' 
     else 'uh??' 
    end role, 
    count(user_id) nr_users from (
     select user_id, group_concat(role_id order by role_id separator ',') roles 
     from roles_users 
     group by user_id 
    ) 
group by role 
order by role; 

順便說一下,你可以使用一個位掩碼更有效地存儲的角色。優點:每個用戶ID只有一列。缺點:難以建立查詢...

+0

我喜歡這個。但是,您是否需要在內部查詢中使用role_id命令來確保返回的字符串始終相同(即'1,2,3'而不是'3,1,2')? – Glenn 2011-12-18 20:51:37

+0

它在group_concat語句本身中,在它被分組之前被排序。 – fge 2011-12-18 20:53:37

+0

對不起,沒有理解。這是一個很好的解決方案。我希望甲骨文有這樣的功能。 – Glenn 2011-12-18 20:56:36

0

不是最優雅,但開始

SELECT user_id 
     ,CASE WHEN (role1 > 0 AND 0 = role2 AND 0 = role3 AND 0 = role4) THEN 'MEMBER' 
     WHEN (role1 > 0 AND role2 > 0 AND 0 = role3 AND 0 = role4) THEN 'ADMIN' 
     WHEN (role1 > 0 AND role2 > 0 AND role3 > 0 AND 0 = role4) THEN 'SELLER' 
     WHEN (role1 > 0 AND 0 = role2 AND 0 = role3 AND role4 > 0) THEN 'PARTNER' 
     ELSE 'Something else' 
     END AS type 
    FROM (
    SELECT user_id 
      ,SUM(CASE role_id WHEN 1 THEN 1 ELSE 0 END) AS role1 
      ,SUM(CASE role_id WHEN 2 THEN 1 ELSE 0 END) AS role2 
      ,SUM(CASE role_id WHEN 3 THEN 1 ELSE 0 END) AS role3 
      ,SUM(CASE role_id WHEN 4 THEN 1 ELSE 0 END) AS role4 
     FROM roles_users 
     GROUP BY user_id 
    ) x 

編輯:我想這是回答錯誤的問題,它顯示每個用戶的類型。

0

這是一個使用INTERSECT和MINUS的解決方案。可悲的是,這些不被MySQL支持,但也許有人會發現這個有用的。

- 查找用戶角色1

SELECT user_id FROM 
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1) 
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1) 

- 找到與角色1和2

SELECT user_id FROM 
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1 
    INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 2) 
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1,2) 

用戶 - 找到與角色1,2用戶,3

SELECT user_id FROM 
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1 
    INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 2 
    INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 3) 
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1,2,3) 

- 查找角色的用戶1,4

SELECT user_id FROM 
(SELECT user_id, role_id FROM roles_users WHERE role_id = 1 
    INTERSECT SELECT user_id, role_id FROM roles_users WHERE role_id = 4) 
MINUS SELECT user_id FROM roles_users WHERE role_id NOT IN (1,4)