2017-04-25 23 views
3
BY COUNTまたはGROUPせずにカウントNとの値を繰り返し

のは、私のような人のidの(1-8)と、人の役割(1-4)のテーブルがあるとしましょう:SELECT重複/

CREATE TABLE personRole (
PersonId int NOT NULL, 
RoleId int NOT NULL 
); 

INSERT INTO personRole 
VALUES 
(1, 1), 
(1, 2), 
(2, 1), 
(2, 3), 
(3, 3), 
(4, 3), 
(1, 4), 
(5, 2), 
(6, 1), 
(7, 1), 
(7, 4), 
(8, 1), 
(8, 2), 
(8, 4) 
; 

私の目標3つの以上の役割や役割を持っている人IDを選択することで具体的には1、2であり、ここで4は私の最初のソリューションです:

SELECT PersonId FROM personRole 
WHERE RoleID in (1,2,4) 
GROUP BY PersonId 
HAVING count(*) >= 3 

しかし、私はそれので、GROUP BYせずにそれを行うように言われました私はこの解決策を思いついたので、遅いです:

SELECT distinct PersonId 
FROM 
(
    SELECT PersonId, count(*) over(partition by PersonId) AS pcount 
    FROM (SELECT * FROM personRole WHERE RoleID in (1,2,4)) AS A 
) AS S 
WHERE pcount >= 3 

私が達成しようとしていることの例を示すために、これらを含めました。 しかし、今私はカウントせずにそれを試みるように言われている。私は現在、このような2連/繰り返す人のIDを持つすべての行を見つけることができています:

SELECT personId 
FROM personRole AS a 
WHERE EXISTS (
    SELECT 1 
    FROM personRole AS a2 
    WHERE a2.PersonId = a.PersonId 
    AND a2.RoleID <> a.RoleID 
); 

しかし、私は、彼らが3回以上繰り返した場合にのみ、それらを選択する方法を見つけようとして立ち往生しています。私が能力があれば、私はちょうどそれと交渉することができると思う:

私の完全な解決策を得るには。私はこれを正しく解決しているのか、間違った方向に行っていますか?

+0

3を超えることはできません。元のクエリを再訪して、それがなぜ遅いのかを調べるべきだと思います。 – Strawberry

答えて

3

「カウントなし」とは、独裁者が集計機能を意味しないのでしょうか?カウント(*)の代わりに常に(1)を合計することができます。

それ以外の場合は、自己結合を試してください。

select a.PersonId, 
    a.RoleId, 
    b.RoleId, 
    c.RoleId, 
    d.RoleId 
from personRole a 
    left join personRole b 
    on a.PersonId = b.PersonId 
    and a.RoleId <> b.RoleId 
left join personRole c 
    on a.PersonId = c.PersonId 
    and a.RoleId <> c.RoleId 
    and b.RoleId <> c.RoleId 
left join personRole d 
    on a.PersonId = d.PersonId 
    and a.RoleId <> d.RoleId 
    and b.RoleId <> d.RoleId 
    and c.RoleId <> d.RoleId 
order by a.PersonId, a.RoleId 
; 

+----------+--------+--------+--------+--------+ 
| PersonId | RoleId | RoleId | RoleId | RoleId | 
+----------+--------+--------+--------+--------+ 
|  1 |  1 |  4 |  2 | NULL | 
|  1 |  1 |  2 |  4 | NULL | 
|  1 |  2 |  4 |  1 | NULL | 
|  1 |  2 |  1 |  4 | NULL | 
|  1 |  4 |  2 |  1 | NULL | 
|  1 |  4 |  1 |  2 | NULL | 
|  2 |  1 |  3 | NULL | NULL | 
|  2 |  3 |  1 | NULL | NULL | 
|  3 |  3 | NULL | NULL | NULL | 
|  4 |  3 | NULL | NULL | NULL | 
|  5 |  2 | NULL | NULL | NULL | 
|  6 |  1 | NULL | NULL | NULL | 
|  7 |  1 |  4 | NULL | NULL | 
|  7 |  4 |  1 | NULL | NULL | 
|  8 |  1 |  2 |  4 | NULL | 
|  8 |  1 |  4 |  2 | NULL | 
|  8 |  2 |  1 |  4 | NULL | 
|  8 |  2 |  4 |  1 | NULL | 
|  8 |  4 |  2 |  1 | NULL | 
|  8 |  4 |  1 |  2 | NULL | 
+----------+--------+--------+--------+--------+ 
20 rows in set (0.00 sec) 

どこc.RoleIdの値を探します句とすることを制限する - などのようなデカルト製品を処分するために、あなたのマジックナンバーを使用します、

select a.PersonId, 
     a.RoleId, 
     b.RoleId, 
     c.RoleId 
from personRole a 
left join personRole b 
    on a.PersonId = b.PersonId 
left join personRole c 
    on a.PersonId = c.PersonId 
where 
    b.RoleId <> a.RoleId 
    and b.RoleId <> c.RoleId 
    and c.RoleId <> a.RoleId 
    and c.RoleId <> b.RoleId 
    and a.RoleId = 1 
    and b.RoleId = 2 
    and c.RoleId = 4 
order by a.PersonId, a.RoleId 
; 

+----------+--------+--------+--------+ 
| PersonId | RoleId | RoleId | RoleId | 
+----------+--------+--------+--------+ 
|  1 |  1 |  2 |  4 | 
|  8 |  1 |  2 |  4 | 
+----------+--------+--------+--------+ 
2 rows in set (0.00 sec) 

あなたはそれがさらにコンパクトにしたい場合あなたはこれだけケースを探している、あなたは左結合とすべて一緒

mysql> select a.PersonId, 
    ->  a.RoleId, 
    ->  b.RoleId, 
    ->  c.RoleId 
    -> from personRole a, 
    ->  personRole b, 
    ->  personRole c 
    -> where 
    ->  a.PersonId = b.PersonId 
    ->  and a.PersonId = c.PersonId 
    ->  and a.RoleId = 1 
    ->  and b.RoleId = 2 
    ->  and c.RoleId = 4 
    -> order by a.PersonId, a.RoleId 
    -> ; 
+----------+--------+--------+--------+ 
| PersonId | RoleId | RoleId | RoleId | 
+----------+--------+--------+--------+ 
|  1 |  1 |  2 |  4 | 
|  8 |  1 |  2 |  4 | 
+----------+--------+--------+--------+ 
2 rows in set (0.00 sec) 
+1

これはすばらしい解決策です!ありがとうございました!和についてのヒントをくれてくれてありがとう、私はそれを私のポケットに入れておきます。私がすべての集合体から制限されているかどうかは不明ですが、あなたは両方のヒントを与えました。 – Ryan

+0

あなたはちょっと説明できますか... ...あなたのために... –

+1

これは、「3回以上繰り返せば選択するだけです」と「質問の役割は特に1,2,4です」ということをどうやって解決しますか? –

2

あなたが行うことができます値の比較を離れて行うことができ、私はそれがより電子になることを知りませんが、自己結合他のソリューションよりも効率的です。あなたがそれらの使用を制限されているようだから、集計関数を取り除くでしょう。

select a.PersonId 
from personRole a 
    join personRole b on a.PersonId = b.PersonId 
     and b.RoleId = 2 
    join personRole c on a.PersonId = c.PersonId 
     and c.RoleId = 4 
where a.RoleId = 1 
関連する問題