2017-08-26 1 views
0

DB - OracleSQL - Filter Ergebnismenge basierend auf Wert

Alle Einschränkungen entfallen.

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)) 

Daten

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 

Ergebnis:

cid eid total_cnt 

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

Gibt es einen Weg, um Kunden in der für jede Übung ids ohne Einträge, um herauszufiltern in Klausel?

Für z.B. Der Kunde 300 hat keine Zeilen für die Trainings-ID 1 oder 2. Dieser Kunde sollte nicht im Ergebnis enthalten sein. Kunde 200 hat keine Zeilen für Übung 1, aber Daten für Übung 2, daher wird erwartet, dass er als Zähler 0 für Übung 1 angezeigt wird.

Wie erhalte ich eine Ergebnismenge wie unten?

Erwartetes Ergebnis:

cid eid total_cnt 

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

Antwort

0

Sie könnten ein inner join statt äußere Verknüpfung verwenden, aber die Join-Bedingung auf dem eid fallen, die in einen CASE WHEN Ausdruck in der select Klausel zu bewegen. Auf diese Weise werden Sie haben die in (1, 2) Bedingung zu wiederholen, obwohl:

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 

Sehen Sie es auf rextester.com laufen.

Ausgang:

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

Alternative:

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

Der richtige Weg, es zu tun:

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 

Sorry, ein leichter Fehler von mir war, (ohne max() Der Code gab ORA-00979: nicht eine GROUP BY-Ausdruck)

+0

Dies ist keine Gruppierung nach Ausdruckfehler. – rayne

+0

Danke, Rayne, ich habe es behoben. – wolfrevokcats

Verwandte Themen