1

これは私の以前に答えた質問への修正です

以下のようなデータがテーブルにあります。

ROLE_ID | USER_ID
------------------
 14     | USER A
 15     | USER A
 11     | USER B
 13     | USER D
 13     | USER A
 15     | USER B
 15     | USER D
 12     | USER C
 15     | USER C

13と15しかないユーザーIDを取得したいので、上記の例に基づいて、取得する必要があるのはUSER D

以下のクエリは私の以前の回答で提供され、そのNOT IN部分は私によって追加されましたが、それは目標を達成していません。

select user_id
  from my_table
 where role_id in (13,15) AND role_id not in (11,14)
 group by user_id.
having count(distinct role_id) = 2
4

5 に答える 5

4

13と15のみを取得するには、次のようにします。

select user_id
from my_table
group by user_id
having max(case when role_id = 13 then 1 else 0 end) = 1 and  -- has 13
       max(case when role_id = 15 then 1 else 0 end) = 1 and  -- has 15
       max(case when role_id not in (13, 15) then 1 else 0 end) = 0 -- nothing else

これにより、13と15がuser_idセットに含まれていることが確認されます。次に、セットに他に何も含まれていないことを確認します。

最初は、caseステートメントでhaving句を使用するのは厄介に思えます。ただし、セット内のさまざまな組み合わせに関する多くのロジックを表現できます。

于 2012-08-29T01:02:36.677 に答える
2

user_idとの組み合わせがユニークであると仮定すると、次のrole_idようなことができます

select user_id
  from my_table
 where role_id in (13,15,11,14) 
 group by user_id.
having sum( case when role_id in (13,15) then 1 else 0 end) = 2
   and sum( case when role_id in (11,14) then 1 else 0 end) = 0

user_idとの組み合わせがrole_id一意でない場合はdistinct、オリジナルのcountを使用する必要があり、状況は少し難しくなります。

于 2012-08-29T00:37:51.657 に答える
0

role_idが13と15(そして他には何もない)のユーザーが欲しい

それを行う1つの方法:

SELECT t13.user_id
FROM   my_table t13
JOIN   my_table t15 ON t13.user_id = t15.user_id
LEFT   JOIN my_table tx ON tx.user_id = t13.user_id AND tx.role_id NOT IN (13,15)
WHERE  t13.role_id = 13
AND    t15.role_id = 15
AND    tx.user_id IS NULL;

これは一意であると想定(role_id, user_id)しています。

これは、関係除算の特殊なケースです。最近、これに対処するための多くの方法を集めました(PostgreSQLとMySQLの場合ですが、そのほとんどはOracleでも機能する基本的なSQLです):
SQLの結果をフィルタリングする方法

NOT EXISTSの別のバリアント:

SELECT t13.user_id
FROM   my_table t13
JOIN   my_table t15 ON t13.user_id = t15.user_id
WHERE  t13.role_id = 13
AND    t15.role_id = 15
AND    NOT EXISTS (
   SELECT 1
   FROM   my_table tx
   WHERE  tx.user_id = t13.user_id
   AND    tx.role_id NOT IN (13,15)
   );
于 2012-08-29T01:34:02.797 に答える
0

実際にはテストしていませんが、次のようなものが機能するはずです。

SELECT USER_ID
FROM MY_TABLE T1
WHERE
    ROLE_ID IN (13, 15)
    AND NOT EXISTS (
        SELECT *
        FROM MY_TABLE T2
        WHERE
            T1.USER_ID = T2.USER_ID
            AND ROLE_ID IN (11, 14)
    )
GROUP BY USER_ID
HAVING COUNT(DISTINCT ROLE_ID) = 2

平易な英語:望ましくないROLE_ID()を含む行があるユーザーのすべての行を無視してNOT EXISTSから、ユーザーが望ましいROLE_IDをすべて持っていることを確認します。

注:{ROLE_ID、USER_ID}にキーがある場合、DISTINCTは必要ありません。


「else」が何であるかを事前に知らずに、(13、15)のみを持ち、他に何もないユーザーを取得するにROLE_ID IN (11, 14)は、内部クエリのinを。に置き換えるだけROLE_ID NOT IN (13, 15)です。

于 2012-08-29T01:53:14.497 に答える
0

私の答えをあなたの元の質問に拡張して、あなたは試してみるかもしれません

(SELECT user_id FROM table WHERE role_id=13
       INTERSECT
SELECT user_id FROM table WHERE role_id=15)
       MINUS
SELECT user_id FROM table WHERE role_id IN (11, 14)

INTERSECTとは両方ともORACLEMINUSに固有であるため、他のソリューションはより一般的ですが、これはより読みやすく、変更が容易です。

ORACLEデータベースにアクセスできないため、テストされていません。

于 2012-08-29T09:11:11.067 に答える