Oracle SQL - simplifying the totals column - sql

I have the below issues that I would like to address:
Is there a way to simplify the Total column?
The bottom row reads as null, I would like that to be "Total" as well.
Is it better to ROLLUP the way I have it, ROLLUP((status))? Or this is exactly same as ROLLUP(status)?
Below is my query:
SELECT
status AS "ROW LABELS",
COUNT(case when source = 'INTERNET' THEN 1 end) AS "INTERNET",
COUNT(case when source = 'SALES' THEN 1 end) AS "SALES",
COUNT(case when source = 'REP' THEN 1 end) AS "REP",
COUNT(case when source = 'COM' THEN 1 end) AS "COM",
(COUNT(case when source = 'INTERNET' THEN 1 end) +
COUNT(case when source = 'SALES' THEN 1 end) +
COUNT(case when source = 'REP' THEN 1 end) +
COUNT(case when source = 'COM' THEN 1 end)
) AS Total
FROM
SOMETABLE
GROUP BY ROLLUP((status))
order by 1;
Below is my data:

If by "simplify" you mean "make the calculation more succinct", then yes. The following will work:
COUNT(CASE WHEN source IN ('INTERNET', 'SALES', 'REP', 'COM') THEN 1 END)
Simply use nvl to convert the NULL to a value: NVL(status, 'TOTAL') AS row_labels
ROLLUP( (status) ) is the same as ROLLUP( status )

Related

SUM value when another column value is DISTINCT

I was wondering how I can SUM the values of a column based on another column's values being distinct like below. I tried the following two ways, each giving errors due to the aggregate function. I am trying to get NonDistinctTotals with the queries below.
SELECT SUM(InvoiceSaleAmt) AS NonDistinctTotals, SUM(case when count(*) over (partition by InvoiceNo) = 1 then InvoiceSaleAmt else 0 END) as DistinctTotals, SUM(CASE WHEN PaymentType= 'CASH' THEN CashTotal ELSE 0 END) AS CashTotal
FROM #InvoiceTable a
group by LocationId, InvoiceNo
Error: Windowed functions cannot be used in the context of another windowed function or aggregate.
SELECT SUM(InvoiceSaleAmt) AS NonDistinctTotals, SUM(CASE WHEN InvoiceNoin (SELECT DISTINCT InvoiceNofrom #InvoiceTable) THEN InvoiceSaleAmt else 0 END) as DistinctTotals, SUM(CASE WHEN PaymentType= 'CASH' THEN CashTotal ELSE 0 END) AS CashTotal
FROM #InvoiceTable a
group by LocationId, InvoiceNo
Error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
Use a subquery:
SELECT SUM(InvoiceSaleAmt) AS NonDistinctTotals,
SUM(case when cnt = 1 then InvoiceSaleAmt else 0 END) as DistinctTotals,
SUM(CASE WHEN PaymentType = 'CASH' THEN CashTotal ELSE 0 END) AS CashTotal
FROM (SELECT it.*, COUNT(*) over (partition by InvoiceNo) as cnt
FROM #InvoiceTable it
) it
GROUP BY LocationId, InvoiceNo

SQL server Calculate with COUNT [duplicate]

This question already has an answer here:
How to use an Alias in a Calculation for Another Field
(1 answer)
Closed 4 years ago.
select
category, count(category) as 'TotalCounts',
COUNT(case kind when 'avail'then 1 else null end) as 'avail',
Count(case kind when 'offers' then 1 else null end) as 'offers',
COUNT(CASE contactMethod WHEN 'SMS' then 1 else null END) as 'SMS',
COUNT(case contactMethod when 'call' then 1 else null end) as 'call',
CONVERT(varchar(254),COUNT (case when max_biz_status='A' OR
max_biz_status ='B' then 1 else null end) * 100 / count(category)) +'%'
as 'Percetange'
from reports
group by category
order by TotalCounts
Instead of calculating again in Convert method i want to use avail* 100 / TotalCounts like i did in order by when i used TotalCounts.
i tried:
CONVERT(varchar(254),avail * 100 / TotalCounts) +'%' as 'Percetange'
but i get 'invalid column name' for avail and TotalCounts
You can't do that because your TotalCounts column is made from your result set.
you can try to use a subquery to contain it then calculation.
if your mssql version support CONCAT function you can use it let the SQL clearer.
SELECT t1.*,CONCAT((max_biz_statusCnt * 100 /TotalCounts),'%')as 'Percetange'
FROM
(
select
category,
count(*) as 'TotalCounts',
COUNT(case kind when 'avail'then 1 else null end) as 'avail',
Count(case kind when 'offers' then 1 else null end) as 'offers',
COUNT(CASE contactMethod WHEN 'SMS' then 1 else null END) as 'SMS',
COUNT(case contactMethod when 'call' then 1 else null end) as 'call',
COUNT (case when max_biz_status='A' OR max_biz_status ='B' then 1 else null end) 'max_biz_statusCnt'
from reports
group by category
) t1
order by TotalCounts
You can't use avail or TotalCounts as you just created them, so they aren't in scope, using a common-table expression is one way to fix this:
WITH cte AS (
SELECT
category,
COUNT(category) AS TotalCounts,
COUNT(case kind WHEN 'avail' THEN 1 ELSE NULL END) AS avail,
COUNT(case kind WHEN 'offers' THEN 1 ELSE NULL END) AS offers,
COUNT(CASE contactMethod WHEN 'SMS' THEN 1 ELSE NULL END) AS SMS,
COUNT(case contactMethod WHEN 'call' THEN 1 ELSE NULL END) AS [call]
FROM
reports
GROUP BY
category)
SELECT
*,
CONVERT(varchar(254),avail * 100 / TotalCounts) +'%' AS Percetange --(sic)
FROM
cte
ORDER BY
TotalCounts;

How can I make two column from same table by two query

I've two query from same table but by two condition but how can I make two column for this two conditional count.
SELECT Count(*) FROM TBL_FT WHERE STATUS = 'X';
SELECT Count(*) FROM TBL_FT WHERE STATUS = 'Y' and
LOGDATE>trunc(sysdate);
You can use conditional aggregation:
SELECT
COUNT(CASE WHEN STATUS = 'X' THEN 1 END),
COUNT(CASE WHEN STATUS = 'Y' AND LOGDATE > trunc(sysdate) THEN 1 END)
FROM TBL_FT
You can also add a WHERE clause:
WHERE STATUS IN ('X', 'Y');
you can use something like this -
SELECT SUM(CASE
WHEN STATUS = 'X' THEN
1
ELSE
0
END) FIRST_VAL,
SUM(CASE
WHEN STATUS = 'Y'
AND LOGDATE > TRUNC(SYSDATE) THEN
1
ELSE
0
END) second_val
FROM TBL_FT;

SQL - How do I simplify this easy query?

I am using SQL Server 2005.
How could I refactor this query?
SELECT Total, Installs, Service, tot.ls_chg_dte_ojb
FROM (SELECT COUNT(*) [Total], ls_chg_dte_ojb
FROM [COMPL_INST_SVC]
GROUP BY ls_chg_dte_ojb) tot
JOIN (SELECT COUNT(*) [Service], ls_chg_dte_ojb
FROM [COMPL_INST_SVC]
WHERE job_class_ojb = 'S'
GROUP BY ls_chg_dte_ojb) svc on svc.ls_chg_dte_ojb = tot.ls_chg_dte_ojb
JOIN (SELECT COUNT(*) [Installs], ls_chg_dte_ojb
FROM [COMPL_INST_SVC]
WHERE job_class_ojb in ('C', 'R')
GROUP BY ls_chg_dte_ojb) ins on ins.ls_chg_dte_ojb = tot.ls_chg_dte_ojb
It looks like the Total and Service counts are counting the same exact thing, so you'll need to fix that, but here's basically how you do the counts in a simpler way:
SELECT
COUNT(CASE WHEN job_class_ojb = 'S' THEN 1 END) AS [Total],
COUNT(CASE WHEN job_class_ojb = 'S' THEN 1 END) AS [Service],
COUNT(CASE WHEN job_class_ojb in ('C', 'R') THEN 1 END) AS [Installs]
FROM
[COMPL_INST_SVC]
Two of your sub-selects are the same. Ignoring the 'Service' one, try something along the lines of
SELECT
SUM(CASE WHEN job_class_ojb = 'S' THEN 1 ELSE 0 END) as Total,
SUM(CASE WHEN job_class_ojb = 'C' or
job_class_ojb = 'R' THEN 1 ELSE 0 END) as Installs
FROM COMPL_INST_SVC
I suspect that the Totals subquery should not include the WHERE job_class_ojb = 'S' condition - if so, I suggest:
SELECT COUNT(*) Total,
SUM(CASE WHEN job_class_ojb = 'S' THEN 1 ELSE 0 END) Service,
SUM(CASE WHEN job_class_ojb in ('C','R') THEN 1 ELSE 0 END) Installs,
ls_chg_dte_ojb
FROM COMPL_INST_SVC
GROUP BY ls_chg_dte_ojb

SQL Query to Calculate two Amounts on the same row

probably a very simple answer but i'm new to T-SQL so could do with some help!
I need a 3rd column that works out TotInc - (minus) TotEx to give me a TotalDisposableIncome
Here is my SQL:
--This gives me the Total Income and Total Expenditure on the same row
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
Thanks!
You could use a Common Table Expression (CTE):
WITH T1 AS
(
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
)
SELECT TotalInc, TotEx, TotalInc - TotEx AS TotalDisposableIncome
FROM T1
Or an ordinary subquery:
SELECT TotalInc, TotEx, TotalInc - TotEx AS TotalDisposableIncome
FROM
(
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
) T1
You can't reference your column aliases elsewhere in your SELECT clause. Here is one alternative.
SELECT TotalInc, TotEx, TotInc - TotEx as TotalDisposable
FROM (
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx
FROM ClaimFinancials
) AS Total
There's more than one way to do it.
WITH T1 AS
(
SELECT
Type,
SUM(Amount as Total
FROM ClaimFinancials
)
SELECT
Inc.Total as TotalInc,
Ex.Total as TotEx,
Inc.Total - Ex.Total AS TotalDisposableIncome
FROM T1 Inc, T2 Ex
where T1.Type = 1 and T2.Type = 2
SELECT
SUM(CASE WHEN Type = '1' THEN Amount ELSE 0 END) as TotalInc,
SUM(CASE WHEN Type = '2' THEN Amount ELSE 0 END) as TotEx,
SUM(CASE
WHEN Type = '1' THEN Amount
WHEN Type = '2' Then -Amount
ELSE 0
END) AS TotalDisposableIncome
FROM ClaimFinancials