SQL:NOT INクエリ

したがって、データベースにはroles_usersという名前のテーブルがあります。これは、ユーザーが持つすべての役割を保持します。ここには、user_id、role_idという2つの列があります。

余分な役割を持たない通常のユーザーは、この表に1行あります。この行はrole_id 1です。

管理ユーザーは、この表に2行あります。 role_id 1の1つ、role_id 2の1つの行

このような:

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

今、どのくらいのユーザー/管理者/売り手/パートナーが存在するかを数えようとしています。

売り手は3行、1つはrole_id 1、role_id 2およびrole_id 3です。

パートナーは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とそれthatsとそれをtheres場合にだけチェックするため、それは、それがメンバーのために、role_id 1、それはパートナー、管理者、売り手を含む必要がありますクエリで意味します。

だから私はこれをどうやって行うことができますか?したがって、メンバーを調べるときには、user_idに2,3,4などの他のrole_idsを持つ行がもうないことを確認する必要があります

1
必要なリレーショナル演算子は、広く知られているディビジョンです「すべての部品を提供するサプライヤ」を参照してください。推奨される読書 here ここここを参照してください。
追加された 著者 onedaywhen,
select distinct user_Idを試してください
追加された 著者 Sparky,

6 答え

group_concat is what you want:

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ごとに1つの列のみ。欠点:クエリを作成するのが難しい...

1
追加された
グループ化される前に順序付けられているのは、group_concatステートメント自体の中にあります。
追加された 著者 fge,
Oracleは wm_concat を持っていますが、 order by できるかどうかはわかりません。
追加された 著者 fge,
私はこれが好き。しかし、返される文字列が常に同じであることを保証するために、内側のクエリでrole_idによる注文が必要ですか(つまり、 '1,2,3'ではなく '3,1,2')?
追加された 著者 Glenn,
はい、申し訳ありませんが、それをキャッチしませんでした。それは素晴らしい解決策です。私はOracleにそのような機能があったらいいと思う。
追加された 著者 Glenn,

売り手とパートナーについて:
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
追加された

これにより、テーブル内の特権とカウントのすべての組み合わせが得られます

SELECT 
    COUNT(*) AS num
    GROUP_CONCAT(role_id ORDER BY role_id) AS privilegeset
FROM roles_users
GROUP BY user_id
0
追加された
ああ!それは本当に機能しますか?この背後にある論理を説明するケア?
追加された 著者 fge,

最も優雅ではないが、スタート

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
追加された

ここには、任意の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"を変更するだけで、ユーザーに持つロールを変更することができます。

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)
0
追加された