简体   繁体   中英

Oracle SQL how to write complex query with multiple joins and groupby

Oracle SQL : I have the below set of queries, all fetching from same table. I wanted to find if there is a way if it all can be combined into one query ?

SELECT COUNT(T.ISSUE_NUMBER) total_cases,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Closed' THEN 1 END) total_close,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Open' THEN 1 END) total_open,
       COUNT(CASE WHEN T.IS_DUPLICATE = 1 THEN 1 END) total_duplicate,
       COUNT(CASE WHEN T.IS_REJECTION = 1 THEN 1 END) total_rejected,
       T.G_SECTOR 
FROM TRANSFORMED T
WHERE T.SERVICE_CENTER_ENGLISH = 'Center' 
AND TO_DATE(T.RAISED_ON)  >= TRUNC(SYSDATE)-30
AND T.IS_DISTORTION = 1
GROUP BY T.G_SECTOR 
ORDER BY 1 DESC

SELECT COUNT(T.ISSUE_NUMBER) total_cases,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Closed' THEN 1 END) total_close,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Open' THEN 1 END) total_open,
       COUNT(CASE WHEN T.IS_DUPLICATE = 1 THEN 1 END) total_duplicate,
       COUNT(CASE WHEN T.IS_REJECTION = 1 THEN 1 END) total_rejected,
       T.AGENCY_NAME,T.DIST_AGENCY_TYPE
FROM TRANSFORMED T
WHERE T.SERVICE_CENTER_ENGLISH = 'Center' 
AND TO_DATE(T.RAISED_ON)  >= TRUNC(SYSDATE)-30
AND T.IS_DISTORTION = 1
GROUP BY T.AGENCY_NAME, T.DIST_AGENCY_TYPE
ORDER BY 1 DESC

SELECT COUNT(T.ISSUE_NUMBER) total_cases,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Closed' THEN 1 END) total_close,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Open' THEN 1 END) total_open,
       COUNT(CASE WHEN T.IS_DUPLICATE = 1 THEN 1 END) total_duplicate,
       COUNT(CASE WHEN T.IS_REJECTION = 1 THEN 1 END) total_rejected,
       T.VIOLATION_ENGLISH,T.DIST_AGENCY_TYPE
FROM TRANSFORMED T
WHERE T.SERVICE_CENTER_ENGLISH = 'Center' 
AND TO_DATE(T.RAISED_ON)  >= TRUNC(SYSDATE)-30
AND T.IS_DISTORTION = 1
GROUP BY T.VIOLATION_ENGLISH, T.DIST_AGENCY_TYPE
ORDER BY 1 DESC
SELECT *
FROM (
SELECT COUNT(T.ISSUE_NUMBER) total_cases,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Closed' THEN 1 END) total_close,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Open' THEN 1 END) total_open,
       COUNT(CASE WHEN T.IS_DUPLICATE = 1 THEN 1 END) total_duplicate,
       COUNT(CASE WHEN T.IS_REJECTION = 1 THEN 1 END) total_rejected,
       T.G_SECTOR, '' AS AGENCY_NAME, '' AS VIOLATION_ENGLISH, '' AS DIST_AGENCY_TYPE 
FROM TRANSFORMED T
WHERE T.SERVICE_CENTER_ENGLISH = 'Center' 
AND TO_DATE(T.RAISED_ON)  >= TRUNC(SYSDATE)-30
AND T.IS_DISTORTION = 1
GROUP BY T.G_SECTOR 

UNION ALL    
SELECT COUNT(T.ISSUE_NUMBER) total_cases,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Closed' THEN 1 END) total_close,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Open' THEN 1 END) total_open,
       COUNT(CASE WHEN T.IS_DUPLICATE = 1 THEN 1 END) total_duplicate,
       COUNT(CASE WHEN T.IS_REJECTION = 1 THEN 1 END) total_rejected,
       '' AS G_SECTOR, T.AGENCY_NAME, '' AS VIOLATION_ENGLISH, T.DIST_AGENCY_TYPE
FROM TRANSFORMED T
WHERE T.SERVICE_CENTER_ENGLISH = 'Center' 
AND TO_DATE(T.RAISED_ON)  >= TRUNC(SYSDATE)-30
AND T.IS_DISTORTION = 1
GROUP BY T.AGENCY_NAME, T.DIST_AGENCY_TYPE

UNION ALL    
SELECT COUNT(T.ISSUE_NUMBER) total_cases,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Closed' THEN 1 END) total_close,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Open' THEN 1 END) total_open,
       COUNT(CASE WHEN T.IS_DUPLICATE = 1 THEN 1 END) total_duplicate,
       COUNT(CASE WHEN T.IS_REJECTION = 1 THEN 1 END) total_rejected,
       '' AS G_SECTOR, '' AS AGENCY_NAME, T.VIOLATION_ENGLISH,T.DIST_AGENCY_TYPE
FROM TRANSFORMED T
WHERE T.SERVICE_CENTER_ENGLISH = 'Center' 
AND TO_DATE(T.RAISED_ON)  >= TRUNC(SYSDATE)-30
AND T.IS_DISTORTION = 1
GROUP BY T.VIOLATION_ENGLISH, T.DIST_AGENCY_TYPE
) A
ORDER BY 1 DESC

Yes, Oracle has advanced mechanisms for grouping data: ROLLUP, CUBE, GROUPING Functions and GROUPING SETS . In your case grouping sets seems promising.

This is my table:

create table t(a, b, c, d, e, f) as (
    select 'A1', 'B1', 'C1', 'D1', 'E1', 701 from dual union all
    select 'A2', 'B1', 'C2', 'D1', 'E2', 702 from dual union all
    select 'A2', 'B1', 'C2', 'D1', 'E3', 703 from dual );

You queries differs only in group by part, and you are naturally selecting different columns which are bases of groups. where conditions and conditional counts are not important. Your selects looks like:

 select a, count(1) from t group by a;

 select b, c, count(1) from t group by b, c;

 select d, e, count(1) from t group by d, e;

You can do this:

select a, b, c, d, e, grouping_id(a, b, c, d, e) grp_id, count(1) cnt 
  from t 
  group by grouping sets( (a, null), (b, c), (d, e) )

which outputs:

A  B  C  D  E      GRP_ID        CNT
-- -- -- -- -- ---------- ----------
A1                     15          1
A2                     15          2
   B1 C1               19          1
   B1 C2               19          2
         D1 E1         28          1
         D1 E2         28          1
         D1 E3         28          1

GROUPING SETS should do what you want:

SELECT T.G_SECTOR, T.AGENCY_NAME, T.DIST_AGENCY_TYPE,
       T.VIOLATION_ENGLISH, T.DIST_AGENCY_TYPE,
       COUNT(T.ISSUE_NUMBER) as total_cases,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Closed' THEN 1 END) as total_close,
       COUNT(CASE WHEN T.DIST_COMPLETED_STATUS = 'Open' THEN 1 END) as total_open,
       COUNT(CASE WHEN T.IS_DUPLICATE = 1 THEN 1 END) as total_duplicate,
       COUNT(CASE WHEN T.IS_REJECTION = 1 THEN 1 END) as total_rejected
FROM TRANSFORMED T
WHERE T.SERVICE_CENTER_ENGLISH = 'Center' AND
      TO_DATE(T.RAISED_ON)  >= TRUNC(SYSDATE)-30 AND
      T.IS_DISTORTION = 1
GROUP BY GROUPING SETS ( (T.G_SECTOR), 
                         (T.AGENCY_NAME, T.DIST_AGENCY_TYPE),
                         (T.VIOLATION_ENGLISH, T.DIST_AGENCY_TYPE)
                       )
ORDER BY total_cases DESC;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM