Sum case when one result bigger than the other - sql

I'm using SQL report builder and wish to calculate the % within turnaround times
my table looks like
Name count within tat
jeff 1 1
jeff 1 0
jeff 1 1
jeff 1 0
i would like it to look like this.
Name count within tat
jeff 4 2 (50%)
The code im using to calculate within tat is
case
when (convert(Decimal(10,2),
(cast(datediff(minute,
(CAST(RequestDate AS DATETIME) + CAST(RequestTime AS DATETIME)),
REQUEST_TESTLINES.AuthDateTime)as float)/60/24))) >
EXP_TAT then '1' else '0' end as [withintat]
How can I sum this column ?

you looking for something like that?
select name , sum(count) total, sum(within_tat)*100 /sum(count) as percent
from Table1
Group by name
LOOK DEMO SQLFIDDLE
EDIT.
OR if you want it exactly as yyou want try this
select name , sum(count) as total, CONCAT(sum(within_tat),' ' ,'(',sum(within_tat)*100 /sum(count), '%',')' ) as percent
from Table1
Group by name
CHECK DEMO HERE

You could wrap it in another SELECT.
SELECT SUM(count), SUM(withintat)
FROM (/*Your original query*/)

yes, you can use case statment inside sum()
but it would need to return a number..
a change in your "within tat" to something like
select case when (convert(Decimal(10,2),
(cast(datediff(minute,
(CAST(RequestDate AS DATETIME) + CAST(RequestTime AS DATETIME)),
REQUEST_TESTLINES.AuthDateTime)as float)/60/24))) >
EXP_TAT
then 1
else 0 end as [withintat]
....
but, if you need the sum and the percentual.
you will need to use this value two times.
and I am sure you dont want to keep replicate code.
so use your actual query as a sub query to sum it may be a good idea...
if you realy dont want to use it as a subquery
you should use a outer apply to gather the value of withintat, doing something like this
select Name
,count(*) as [count]
,sum(OA.[withintat]) as [withintat]
,sum(OA.[withintat])*100/count(*) as [percent]
,cast(sum(OA.[withintat]) as varchar(max))+' ('+cast(sum(OA.[withintat])*100/count(*) as varchar(max))+' %)' as [withintat_and_percent]
from your_actual_query
outer apply(select case when (convert(Decimal(10,2),
(cast(datediff(minute,
(CAST(RequestDate AS DATETIME) + CAST(RequestTime AS DATETIME)),
REQUEST_TESTLINES.AuthDateTime)as float)/60/24))) > EXP_TAT
then 1
else 0 end as [withintat]
)OA
where ....

I would use an IF in this case (pun aside). I tried to reduce the complexity of your comparison, but without seeing some actual data, it's a best guess.
select
name,
count(name) as count,
concat(
sum(if(datediff(minute,
(cast(RequestDate AS DATETIME) +
cast(RequestTime AS DATETIME)),
REQUEST_TESTLINES.AuthDateTime) / 60 / 24 > EXP_TAT, 1, 0 )),
' (',
format(
(sum(if(datediff(minute,
(cast(RequestDate AS DATETIME) +
cast(RequestTime AS DATETIME)),
REQUEST_TESTLINES.AuthDateTime) / 60 / 24 > EXP_TAT, 1, 0 )
)/count(name))*100,1),
'%)'
) as 'within tat'

Related

How to use CASE WHEN in group by

I want to use group by for the table NRW_MONTH_DATA.
SELECT [OBJECT_ID]
,[YEAR_MONTH]
,[SELLING_AMOUNT]
,[DEFAULT_SELLING_DATA]
,[LOCK_SELLING_AMOUNT]
,[RGCB]
,[ICKZ]
,[YCKZ]
FROM [dbo].[NRW_MONTH_DATA]
IF LOCK_SELLING_AMOUNT is 0 then group by OBJECT_ID and calculate the sum of [RGCB],[ICKZ] and [YCKZ]
SELECT #SELLING_AMOUNT=(ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID
AND YEAR_MONTH >=#SELLING_CENSUS_START_YM
AND YEAR_MONTH <=#SELLING_CENSUS_END_YM
GROUP BY OBJECT_ID
Now I want to add a condition that if LOCK_SELLING_AMOUNT is 1 , I need to
SELECT #SELLING_AMOUNT=ISNULL(SUM(DEFAULT_SELLING_DATA),0)
ELSE use original result to calculate the sum of the 3 columns.
I use CASE WHEN but is seems that I could not use it in group by
SELECT #SELLING_AMOUNT=
CASE LOCK_SELLING_AMOUNT WHEN 1 THEN SELLING_AMOUNT
ELSE (ISNULL(SUM(YCKZ),0)+ISNULL(SUM(RGCB),0)+ ISNULL(SUM(ICKZ),0))
END
The error is like
The column'dbo.NRW_MONTH_DATA.LOCK_SELLING_AMOUNT' in the select list is invalid because the column is not included in the aggregate function or GROUP BY clause.
Thank you in advance.
I need the group by to calculate the sum of them. Each row has an object_id and a LOCK_SELLING_AMOUNT and other columns for one month, I want to use group to calculate the sum during month span.
It works well when I do not consider the LOCK_SELLING_AMOUNT
First, you don't want GROUP BY. So just use:
SELECT #SELLING_WATER = (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;
Now, the problem is that a column can change values on different rows. So, what row does LOCK_SELLING_AMOUNT come from? We could assume it is the same on all rows. Or perhaps you want an aggregation function:
SELECT #SELLING_WATER = (CASE WHEN MAX(LOCK_SELLING_AMOUNT) = 1
THEN MAX(CASE WHEN LOCK_SELLING_AMOUNT = 1 THEN SELLING_AMOUNT END)
ELSE (COALESCE(SUM(YCKZ), 0) + COALESCE(SUM(RGCB), 0)+ COALESCE(SUM(ICKZ), 0))
END)
FROM [dbo].[NRW_MONTH_DATA]
WHERE OBJECT_ID=#OBJECT_ID AND
YEAR_MONTH >= #SELLING_CENSUS_START_YM
YEAR_MONTH <= #SELLING_CENSUS_END_YM;

Assign Label to Dummy Variable in Aggregate Query

I have the following query which works great. I would simply like to label the output (see below) following the dummy variables I created; '7a-7p' '7p-7a'.
Select
count([SHIFT_Type]) as Count
FROM
(
Select
CASE WHEN Checkin_hour >= 7 and Checkin_hour < 19 then '7a-7p' else '7p-7a' END AS [SHIFT_Type]
FROM (
Select *,
CONVERT(VARCHAR(10),CHECKIN_DATE_TIME,111) as Checkin_date, DATEPART(Hour, CHECKIN_DATE_TIME) as Checkin_hour, DATEPART(DW, CHECKIN_DATE_TIME) as Day_of_Week, [Day] = DATENAME(WEEKDAY, CHECKIN_DATE_TIME),
Row_Number () Over (Partition BY Patient_Fin order BY Patient_Fin) as RowNumber
FROM COVID_TAT
WHERE (CHECKIN_DATE_TIME > #StartDate and CHECKIN_DATE_TIME < #EndDate) and PT_DISCH_DISPO not like '%Error%'
and PT_DISCH_DISPO not like '%no show%' and PT_DISCH_DISPO not like'%Left Without Treatment%' and DOCTORSEE_DATE_TIME not like 'null'
and TRACK_GROUP like '%ED Track%'
)sub
)sub
Group By [SHIFT_Type]
CURRENT OUTPUT
Count
1 64
2 39
DESIRED OUTPUT
Count
7a-7p 64
7p-7a 39
The "label" is already available in the intermediate subquery, and you use it as a
GROUP BY column in the outer query. Just add it to the SELECT clause:
SELECT [SHIFT_Type], count([SHIFT_Type]) as Count
FROM ...
GROUP BY [SHIFT_Type]

SQL Increment column value in select statement

I'm trying to write a Select statement that increments a column value by 50, but the range can end up being 200,000 so I can't do it all in a case statement manually.
Something similar to this, but instead of manually writing the increments
Select count(order_id) as order_count,
case when revenue between 0 and 50 then ‘$50’
when order_value between 51 and 100 then ‘$100’
else ‘over $101’
end as revenue_bucket
from Orders
group by 2
Turn your revenue into the bucket value, then make string out of it:
SELECT count(order_id) AS order_count,
'$' || ((((revenue - 0.01)/50)::int + 1) * 50)::text AS revenue_bucket
FROM Orders
GROUP BY 2;
This obviously runs well past $200,000.
You can work with modulo to get this. Limit would be 101 in your example. All you have to do, is cast the result in a string and add the $ before it
Select count(order_id) as order_count,
case when revenue < limit then revenue - (revenue % 50) + 50
else ‘over $101’
end as revenue_bucket
from Orders
group by 2
You can round to the nearest 50 with div (integer division):
revenue div 50 * 50
To round up instead of down:
(revenue div 50 + 1) * 50
To include 50 in the next bracket (so 50 as $50 instead of $100):
((revenue-1) div 50 + 1) * 50
Example query:
select revenue
, concat('$', ((revenue-1) div 50 + 1) * 50) as revenue_bucket
from YourTable
See it working at SQL Fiddle.
figured out something similar
select floor((revenue+49)/50)*50 as revenue_bucket,
count(1) as order_count
from Orders
group by 1;

How do I add a column with the same value for each row?

I was asked to do a search against our database and to explain the number of clients in the 5 different age ranges. I know I can run the same query five times. However, i was hoping to be able to create one query that would do the whole job.
To my knowledge, I need to do 5 queries and then use "UNION" to connect the different queries.
The issue is that for each query i want to add a column that says "age range" and then put some text to name the group.
The SQL I came up with was:
SELECT COUNT(CLIENT_ID) AS Client_Count, "0 to 19" AS [Age Group]
FROM dbo.CLIENTS
WHERE (DATEDIFF(year, DOB, GETDATE()) BETWEEN 0 AND 19)
While I hoped this would work, it expects the 0 to 19 to be a column. How would I let it know that I'm just trying to pass it a fixed value?
Once I get this to work, they would then like that I the values as a percentage of the total. Any help is appreciated.
This should work. Try single quotes.
SQL uses single quotes to denote string text. Seems like it would be able to interpret double quotes, but there you have it.
The following should give you a good starting point I think:
;with AgeRanges(Low, High) as (
select 0, 19
union select 20, 39
union select 40, 59
union select 60, 79
union select 80, 1000
)
select
count(CLIENT_ID) as Client_Count,
convert(varchar, Low) + ' to ' + convert(varchar, High) as [Age Group]
from
dbo.CLIENTS
inner join AgeRanges
on DATEDIFF(year, DOB, getdate()) BETWEEN Low and High
Change your speach marks. E.g:
SELECT '0 to 19' AS [Age Group]
In Full:
SELECT COUNT(CLIENT_ID) AS Client_Count, '0 to 19' AS [Age Group]
FROM dbo.CLIENTS
WHERE (DATEDIFF(year, DOB, GETDATE()) BETWEEN 0 AND 19)
Not sure if I got it right, but if you want the results in columns, you can do something like this:
SELECT
[0 to 19] = COUNT(CASE WHEN DATEDIFF(year, DOB, GETDATE()) BETWEEN 0 AND 19 THEN 1 END),
[20 to 39] = COUNT(CASE WHEN DATEDIFF(year, DOB, GETDATE()) BETWEEN 20 AND 39 THEN 1 END),
…
FROM dbo.Clients

i need to use the sum of the value in 1 column as part of a ref in another column in a view

i have a view as below.
SELECT TOP (100) PERCENT 'SA' AS Doc_Type1, 'A' + SUBSTRING('000000', 1, 6 - LEN(CAST(dbo.companies.companyId AS varchar(10))))
+ CAST(dbo.companies.companyId AS varchar(10)) AS Client_ID, 1200 AS Bank_Nom, 0 AS Department, CONVERT(nvarchar(20),
dbo.invoices.invoiceDatePaid, 103) AS Cleared_Date, 'Bacs' AS Payment_type, dbo.invoices.invoiceId, dbo.invoices.invoiceTotal AS Value, '9' AS vat,
' ' AS bllank, 1 AS Ex_rate
FROM dbo.invoices INNER JOIN
dbo.companies ON dbo.invoices.invoiceCompanyId = dbo.companies.companyId
WHERE (dbo.invoices.invoiceDatePaid >= DATEDIFF(DAY, 1, CURRENT_TIMESTAMP)) AND (dbo.invoices.invoiceDatePaid < DATEDIFF(DAY, 0,
CURRENT_TIMESTAMP)) AND (dbo.companies.companyPaymentType = 3)
ORDER BY dbo.invoices.invoiceId DESC
In the Payment_Type column i want to add the SUM of the Value column to the word 'Bacs' so it reads 'Bacs £sum' to 2 decimal places. Could you help please, regards and thanks for all the help and suggestions already provided
I'm not very much clear to what exactly you need. You need complete sum of entire column to be displayed or in a group manner, but here is what you can try..Add the sum(Value) after converting it to varchar,which is necessary as two data types has to be varchar to concenate and group by all the remaining columns..something like this
....
,'Bacs'+cast(sum(dbo.invoices.invoiceTotal)
as varchar) AS Payment_type
...
group by all remaining columns
...
order by clause
I don't know whether it even close to what you need but it's just a try to help :-)