2017-08-26 29 views
0

DB - OracleSQL - 値に基づいて結果セットを除外します

すべての制約が省略されています。

create table customer (cid number(10), cname varchar(50)); 

create table exercise (eid number(10), ecode varchar(2)); 

-- mapping table 
create table customer_exercise (cid number(10), eid number(10), cnt number(10)) 

データ

Customer table 

100 e1 
200 e2 
300 e3 
400 e4 

Exercise table 

1  c1 
2  c2 
3  c3 
4  c4 

Customer_Exercise 

cid eid count 
100 1 20 
200 2 50 
100 2 30 
300 4 10 

SQL:

SELECT c.cid 
     ,e.eid 
     ,COALESCE(SUM(ce.cnt), 0) AS total_cnt 
    FROM customer c 
     CROSS JOIN exercise e 
     LEFT JOIN customer_exercise ce 
      ON  ce.cid = c.cid 
       AND ce.eid = e.eid 
    WHERE  c.cid IN (100, 200, 300) 
     AND e.eid IN (1, 2) 
GROUP BY c.cid, e.eid 

結果:

cid eid total_cnt 

100 1  20 
100 2  30 
200 1  0 
200 2  50 
300 1  0 
300 2  0 

のあらゆる運動IDのエントリを持たない顧客をフィルタリングする方法はありますin節?

顧客300は、運動id1または2のための行を有していない。この顧客は、結果にあってはならない。顧客200は練習1の行がないが、練習2のデータがあるので、練習1のカウント0として表示されることが期待されます。

次のような結果セットを得るにはどうすればよいですか?

cid eid total_cnt 

100 1   20 
100 2   30 
200 1   0 
200 2   50 

答えて

0

あなたはinner joinの代わりに、外部結合を使用しますが、select句のCASE WHEN式にそれを移動し、eidに結合条件をドロップすることができます:結果予想

。この方法は、あなたはしかしin (1, 2)状態を繰り返す必要があります:

SELECT  c.cid 
     , e.eid 
     , COALESCE(SUM(CASE e.eid WHEN ce.eid THEN ce.cnt ELSE 0 END), 0) AS total_cnt 
FROM  (
       SELECT DISTINCT eid 
       FROM exercise 
       WHERE eid IN (1, 2)) e 
CROSS JOIN customer c 
INNER JOIN customer_exercise ce 
     ON ce.cid = c.cid 
     AND ce.eid IN (1, 2) 
WHERE  c.cid IN (100, 200, 300) 
GROUP BY c.cid 
     , e.eid 
ORDER BY 1, 2 

は、それがrextester.com上で実行を参照してください。

出力:

cid | eid | total_cnt 
----+------+---------- 
100 | 1 |  20 
100 | 2 |  30 
200 | 1 |  0 
200 | 2 |  50 

オルタナティブ:

SELECT  c.cid 
     , e.eid 
     , COALESCE(SUM(CASE e.eid WHEN ce.eid THEN ce.cnt ELSE 0 END), 0) AS total_cnt 
FROM  exercise e 
CROSS JOIN customer c 
INNER JOIN customer_exercise ce 
     ON ce.cid = c.cid 
     AND ce.eid IN (1, 2) 
WHERE  c.cid IN (100, 200, 300) 
     AND e.eid IN (1, 2) 
GROUP BY c.cid 
     , e.eid 
ORDER BY 1, 2 
0

それを行うための正しい方法:

with t as (
    SELECT c.cid 
      ,e.eid 
      ,COALESCE(SUM(ce.cnt), 0) AS total_cnt 
       ,count(max(ce.cnt))over(partition by c.cid) ce_cnt 
     FROM customer c 
      CROSS JOIN exercise e 
      LEFT JOIN customer_exercise ce 
       ON  ce.cid = c.cid 
       AND ce.eid = e.eid 
    WHERE  c.cid IN (100, 200, 300) 
      AND e.eid IN (1, 2) 
    GROUP BY c.cid, e.eid 
) 
select t.cid,t.eid,t.total_cnt from t where t.ce_cnt >0 

申し訳ありませんが、私の部分に若干のミスは最大なし(あったが、 ORA-00979:GROUP BY式ではない)

+0

これは、式エラーによるグループではありません。 – rayne

+0

ありがとう、レイイン、私はそれを修正しました。 – wolfrevokcats

関連する問題