How do I change a constant value to a column header in SQL? - sql

The SQL query:
select type,count(*), 'Active'
from file where removed = '0'
union all
select type,count(*), 'Removed'
from file where removed = '1'
gives:
TYPE COUNT ( * ) Constant value
A 24,168 Active
A 1 Removed
B 8,280 Active
B 1,263 Removed
However, how can I change the SQL to get:
TYPE Active Removed
A 24,168 1
B 8,280 1,263
Supplementary optional question: and what's the best way to include the following total?
TYPE Active Removed
A 24,168 1
B 8,280 1,263
Total 32,448 1,264
This is my best answer to the supplementary, please let me know if you see any flaws or improvements:
select
type,
sum(CASE WHEN removed = '0' THEN 1 ELSE 0 END) 'Active',
sum(CASE WHEN removed = '1' THEN 1 ELSE 0 END) 'Removed'
from file
Group by type
union all
select 'Total',
sum(CASE WHEN removed = '0' THEN 1 ELSE 0 END) 'Active',
sum(CASE WHEN removed = '1' THEN 1 ELSE 0 END) 'Removed'
from file
Thank you to everyone who commented or answered, your help is appreciated.

You can try:
select
type,
sum(CASE WHEN removed = '0' THEN 1 ELSE 0 END) 'Active',
sum(CASE WHEN removed = '1' THEN 1 ELSE 0 END) 'Removed'
from file
Group by type

Use case expressions to do conditional aggregation:
select type,
count(case when removed = '0' then 1 end) as "Active",
count(case when removed = '1' then 1 end) as "Removed"
from file
group by type
If there are many rows with other removed values than 0/1, and the column is indexed, you can throw in a
WHERE removed IN ('0','1')
to speed things up!

In order to get totals into the answer without union try:
select
coalesce(type, 'Totals') type,
sum(CASE WHEN removed = '0' THEN 1 ELSE 0 END) Active,
sum(CASE WHEN removed = '1' THEN 1 ELSE 0 END) Removed
from file
Group by rollup(type)
This works for v6.1 and later.

Related

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 percentage with rows same table with different where condition

I want to do a query like:
select
count(asterisk) where acción='a'/count(asterisk) where acción='b' * 100
from
same_table
grouped by day
but I don't want use subquery, is it possible with joins?
I`m not sure the syntax is correct, but you can use something like this:
SELECT day,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A,
SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) AS SUM_B,
SUM(CASE WHEN "acción" = 'a' THEN 1 ELSE 0 END) AS SUM_A / SUM(CASE WHEN "acción" = 'b' THEN 1 ELSE 0 END) * 100 AS result
FROM your_table
GROUP BY day
The concept is to actually sum the the values that you need, instead of count.

Avoiding a divide by zero error in a case statement

I am getting a divide by zero error in my script.
Can anyone please help.
I am trying to divide two records and one of them has zero in it. I dont want to lose the row, please advise.
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Paid in 24hrs",
COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
You can introduce a second case to check the result of the sum:
case
when sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end) > 0
then COUNT([MONTH_OF_SUSPENSION])/sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end)
else 0 /* a default value that makes sense to you */
end as "Achieved"
Looking at your code I could assume you are using MSSQL and therefore you could use nullif which returns null if two arguments are equal. So for example your code could look like :
COUNT([MONTH_OF_SUSPENSION])/nullif(sum(case when [PAYMENT_<=24HRS] = 'Y' then 1 else 0 end),0) as "Achieved"
What it does is if the value of the sum operator is equal 0 then the divisor is turn from zero into null and that will result in the entire equation to become null.
use another case statement to check the result of your sum
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Paid in 24hrs",
case
when sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) = 0 then 'whatever you want in this case'
else COUNT([MONTH_OF_SUSPENSION])/sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "Achieved"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
although this is pretty nasty looking, so you could tidy it up a bit with a sub-select:
select
year,
month,
request,
PaidIn24hrs,
case
when PaidIn24hrs = 0 then 'whatever you want in this case'
else request/PaidIn24hrs
end as "Achieved"
from
(
select DATEPART(Year,Request_date) as "Year",
DATEPART(Month,Request_date) as "Month",
COUNT([MONTH_OF_SUSPENSION]) as "Request" ,
sum(case
when [PAYMENT_<=24HRS] = 'Y' then 1
else 0
end) as "PaidIn24hrs"
FROM suspension_br
where REQUEST_STATUS = 'OTHERS'
GROUP BY DATEPART(Year,Request_date),DATEPART(Month,Request_date)
)

SQL Do not return column if value is zero

This query returns one row with columns Ready, Processing, Complete, Failed and Error with totals for each. Is there a way to rewrite this query so that columns that have a total of zero are not returned?
I'm using this to populate the mschart control and I don't wan't labels on the chart if there are 0 instances of that category.
SELECT
SUM(CASE WHEN Status = 'R' THEN 1 ELSE 0 END) AS Ready,
SUM(CASE WHEN Status = 'P' THEN 1 ELSE 0 END) AS Processing,
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) AS Complete,
SUM(CASE WHEN Status = 'F' THEN 1 ELSE 0 END) AS Failed,
SUM(CASE WHEN Status = 'E' THEN 1 ELSE 0 END) AS Error
FROM MailDefinition
No, because the shape of the query (the fields it contains) has to be known. Only the data can change, and that is what you should be looking for. You can dynamically remove or hide labels based on 0 or null data in a column.
What I would do is take what you have, throw it into an unpivot, then remove all of the 0 records.
select
Type,
Sum
from
(
SELECT
SUM(CASE WHEN Status = 'R' THEN 1 ELSE 0 END) AS Ready,
SUM(CASE WHEN Status = 'P' THEN 1 ELSE 0 END) AS Processing,
SUM(CASE WHEN Status = 'C' THEN 1 ELSE 0 END) AS Complete,
SUM(CASE WHEN Status = 'F' THEN 1 ELSE 0 END) AS Failed,
SUM(CASE WHEN Status = 'E' THEN 1 ELSE 0 END) AS Error
FROM MailDefinition
) a
unpivot
(
Sum for Type in ([Ready],[Processing],[Complete],[Failed],[Error])
) u
where Sum>0
That does, of course, entail changing your chart some.

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