Reputation: 63
I have the below data in an Oracle table which I'm trying to perform calculations based on TYPE & QT columns.
TYPE QT STATUS CNT
---- -- ------ ---
E A YES 123
E A NO 2540
E D YES 2
E D NO 787
O A YES 884
O A NO 6957
O D YES 25
O D NO 1360
Looks like my expected output now is different.. like below :
TYPE TOTAL A A&Y
---- ----- ---- -----
E+O 12678 10504 1007
E 3452 2663 123
My old oracle sql is below but the output is wrong when calculating the percentages:
SELECT * FROM (
SELECT NVL(SUM(DECODE(A.QT,'A',A.CNT,'D',A.CNT)),0) AS "TOTAL",
NVL(SUM(DECODE(A.QT,'A',A.CNT)),0) AS "A ALL",
NVL(SUM(DECODE(A.QT,'A',ROUND(100*(NVL(A.CNT,0)/ A.CNT),2))),0) "A ALL %",
NVL(SUM(DECODE(A.STATUS,'E',A.CNT)),0) AS "E TOTAL",
NVL(SUM(DECODE(A.STATUS,'E',DECODE(A.QT,'A',A.CNT))),0) AS "E & A TOTAL"",
NVL(SUM(DECODE(A.STATUS,'E',ROUND(100 * SUM((DECODE(A.QT,'A',A.CNT)) / SUM(A.CNT)),3))),0) "E & A %"
FROM ALLIN A)
Upvotes: 0
Views: 16976
Reputation: 7846
Maybe you could consider using Case expressions instead of Decode() function. The Decode() function could be a bit faster but the readability is always in favour of Case expressions:
Select total, a_all, Round( a_all * 100 / total, 2) a_all_pct,
e_total, ea_total, Round( ea_total * 100 / e_total, 2) ea_pct
From ( SELECT SUM(cnt) as total,
SUM(Case When qt = 'A' Then cnt Else 0 End) as a_all,
SUM(Case When type = 'E' Then cnt Else 0 End) as t_total,
SUM(Case When type || qt = 'EA' Then cnt Else 0 End) as ea_total
FROM allin )
/* R e s u l t :
TOTAL A_ALL A_ALL_PCT E_TOTAL EA_TOTAL EA_PCT
----- ------ ---------- -------- --------- --------
12678 10504 82.85 3452 2663 77.14 */
... the same result using just one query (no subquery - no cte)
Select SUM(cnt) as total,
SUM(Case When qt = 'A' Then cnt Else 0 End) as a_all,
Round( SUM(Case When qt = 'A' Then cnt Else 0 End) * 100 / SUM(cnt), 2 ) as a_all_pct,
--
SUM(Case When type = 'E' Then cnt Else 0 End) as e_total,
SUM(Case When type || qt = 'EA' Then cnt Else 0 End) as ea_total,
Round( SUM(Case When type || qt = 'EA' Then cnt Else 0 End) * 100 / SUM(Case When type = 'E' Then cnt Else 0 End), 2 ) as ea_pct
From allin
See the fiddle here.
Upvotes: 0
Reputation: 181047
You can rewrite the query in a little more readable way using a common table expression;
WITH cte AS (
SELECT
SUM(cnt) total,
SUM(DECODE(qt, 'A', cnt, 0)) a_all,
SUM(DECODE(type, 'E', cnt, 0)) e_total,
SUM(DECODE(type||qt, 'EA', cnt, 0)) ea_total
FROM allin
)
SELECT
total, a_all, ROUND(a_all/total*100, 2) a_percent,
e_total, ea_total, ROUND(ea_total/e_total*100, 2) ea_percent
FROM cte;
This query generates the expected result and is a bit easier to read and debug. The EA
part is assuming that qt and type are each one letter, so a concatenation of them matches EA. If that is not true, I recommend using a CASE
instead, a'la;
SUM(CASE WHEN type = 'E' AND qt = 'A' THEN cnt ELSE 0 END) ea_total
Upvotes: 0