2017-05-18 11 views
1

での選択や除外グループIは、次のようなテーブルを持っている:SQL:多くのID

| id | Category | 
|----|----------| 
| 1 | Red  | 
| 1 | Cat  | 
| 2 | Blue  | 
| 3 | Yellow | 
| 3 | Dog  | 
| 3 | Bike  | 
| 4 | Blue  | 
| 4 | Cat  | 

私が欲しいものは、idでグループにされ、以下の特徴のすべての3つを持っているだけで、それらのIDを保ちます:

  1. 少なくとも1色(赤、黄、青)
  2. 少なくとも1動物(犬、猫、魚)
  3. ませ輸送のいずれかのモード(自転車、車、バス)

は、したがって、上記の表の例では、私は1と4で維持し、グループたいが、2と3

を除外するここで私が持っているコードは、これまでのところです:

SELECT id 
FROM table 
GROUP BY id 
HAVING( (sum(case when (code_value IN ('Red', 'Yellow', 'Blue') then 1 else 0 end) > 0) 
      AND 
      (sum(case when (code_value IN ('Cat', 'Dog', 'Fish') then 1 else 0 end) > 0) 
      AND 
      (sum(case when (code_value IN ('Bike', 'Car', 'Bus') then 0 else 1 end) > 0) 
     ) 

このコンセプトはうまくいくようですが、非常に遅いです。他の誰かがこれについてもっと良い考えを持っているのだろうかと思います。これが機能することに注意してください、私は3つ以上の特性を持つケースがありますので、簡単に拡張できるのが理想的です。

+0

ああ、お詫び申し上げます、それはMySQLです – Corwin

答えて

0

最初に、グループ3のメンバーの少なくとも1つを持つIDを計算できます。その後、最初にそれらのIDを除いて。したがって、このような何か:

SELECT id 
FROM table 
where id NOT IN 
(
select id from table where code_value in ('Bike', 'Car', 'Bus') 
) 
GROUP BY id 
HAVING( (sum(case when (code_value IN ('Red', 'Yellow', 'Blue')) then 1 else 0 end)>0 
AND 
      sum(case when (code_value IN ('Cat', 'Dog', 'Fish')) then 1 else 0 end)>0 
)) 
+0

はい、ありがとうございます。 Gordonの考え方と同様に、GROUP BYコマンドがデータを制限する前に多くのデータを制限しています。 – Corwin

0

は際限なく拡大することができます別のルックアップテーブルでの選択特性、colorsTable、a​​nimalsTable、vehiclesTableを(個別のcode_valueデータと各)、保存することを検討してください。

SELECT t.id  
FROM mytable As t 
LEFT JOIN 
    (SELECT s1.id, count(*) As cnt1 
    FROM myTable s1 INNER JOIN colorsTable s2 
    ON s1.code_value = s2.code_value 
    GROUP BY s1.id) As a 
ON t.id = a.id 

LEFT JOIN 
    (SELECT s1.id, count(*) As cnt2 
    FROM myTable s1 INNER JOIN animalsTable s2 
    ON s1.code_value = s2.code_value 
    GROUP BY s1.id) As b 
ON t.id = b.id 

LEFT JOIN 
    (SELECT s1.id, count(*) As cnt3 
    FROM myTable s1 INNER JOIN vehiclesTable s2 
    ON s1.code_value = s2.code_value  
    GROUP BY s1.id) As c 
ON t.id = c.id 

WHERE a.cnt1 > 0 AND b.cnt2 > 0 AND c.cnt3 IS NULL 
GROUP BY t.id 
0

これは、パフォーマンスに影響を与えませんが、私は、クエリを記述します:次に、あなたのメインの集計クエリに派生テーブル(またはビュー)としてそれらを結合するあなたが書く場合、

その後
HAVING sum(code_value IN ('Red', 'Yellow', 'Blue')) > 0 AND 
     sum(code_value IN ('Cat', 'Dog', 'Fish')) > 0 AND 
     sum(code_value IN ('Bike', 'Car', 'Bus')) = 0 

SELECT id 
FROM table 
WHERE code_value IN ('Red', 'Yellow', 'Blue', 'Cat', 'Dog', 'Fish', 'Bike', 'Car', 'Bus') 
GROUP BY id 
HAVING sum(code_value IN ('Red', 'Yellow', 'Blue')) > 0 AND 
     sum(code_value IN ('Cat', 'Dog', 'Fish')) > 0 AND 
     sum(code_value IN ('Bike', 'Car', 'Bus')) = 0 

次に、GROUP BYより前のデータのサイズが縮小されます。このバージョンでは、table(code_value, id)のインデックスを利用することもできます。これは、データの分布に応じて、パフォーマンスに少し役立ちます。

+0

はい、これは大幅に役立ちます。ありがとうございました。 – Corwin

関連する問題