how to sum two column within single case statement - sql

The query below returns 2 rows, but actually I need only one;
select Datename(month, m.CreatedDate) as [Ay], sum(case when h.Cinsiyet=1 then 1 else 0 end) as [Group1], sum(case when h.Cinsiyet=2 then 1 else 0 end) as [Group2] from Muayene.Muayene m with(nolock)
join Ortak.Hasta h with(nolock) on m.HastaTc = h.HastaTc
group by h.Cinsiyet, Datename(month, m.CreatedDate)
result:
MonthName Group1 Group2
April 4500 0
April 0 9000
Expected Result:
MonthName Group1 Group2
April 4500 9000
I know I can do it wrapping the query with another select statement and Group by month and Sum these results.. But its not efficient and looks dirty code.
How can I make a trick to get expected result without make another sum statement?

FIx the GROUP BY:
select Datename(month, m.CreatedDate) as [Ay],
sum(case when h.Cinsiyet = 1 then 1 else 0 end) as [Group1],
sum(case when h.Cinsiyet = 2 then 1 else 0 end) as [Group2]
from Muayene.Muayene m join
Ortak.Hasta h
on m.HastaTc = h.HastaTc
group by Datename(month, m.CreatedDate);

Related

Count average with multiple conditions

I'm trying to create a query which allows to categorize the average percentage for specific data per month.
Here's how my dataset presents itself:
Date
Name
Group
Percent
2022-01-21
name1
gr1
5.2
2022-01-22
name1
gr1
6.1
2022-01-26
name1
gr1
4.9
2022-02-01
name1
gr1
3.2
2022-02-03
name1
gr1
8.1
2022-01-22
name2
gr1
36.1
2022-01-25
name2
gr1
32.1
2022-02-10
name2
gr1
35.8
...
...
...
...
And here's what I want to obtain with my query (based on what I showed of the table):
Month
<=25%
25<_<=50%
50<_<=75%
75<_<=100%
01
1
1
0
0
02
1
1
0
0
...
...
...
...
...
The result needs to:
Be ordered by month
Have the average use for each name counted and categorized
So far I know how to get the average of the Percent value per Name:
SELECT Name,
AVG(Percent)
from `table`
where Group = 'gr1'
group by Name
and how to count iterations of Percent in the categories created for the query:
SELECT EXTRACT(MONTH FROM Date) as Month,
COUNT(CASE WHEN Percent <= 25 AND Group = 'gr1' THEN Name END) `_25`,
COUNT(CASE WHEN Percent > 25 AND Percent <= 50 AND Group = 'gr1' THEN Name END) `_50`,
COUNT(CASE WHEN Percent > 50 AND Percent <= 75 AND Group = 'gr1' THEN Name END) `_75`,
COUNT(CASE WHEN Percent > 75 AND Percent <= 100 AND Group = 'gr1' THEN Name END) `_100`,
FROM `table`
GROUP BY Month
ORDER BY Month
but this counts all iterations of every name where I want the average of those values.
I've been struggling to figure out how to combine the two queries or to create a new one that answers my need.
I'm working with the BigQuery service from Google Cloud
This query produces the needed result, based on your example. So basically this combines your 2 queries using subquery, where the subquery is responsible to calculate AVG grouped by Name, Month and Group, and the outer query is for COUNT and "categorization"
SELECT
Month,
COUNT(CASE
WHEN avg <= 25 THEN Name
END) AS _25,
COUNT(CASE
WHEN avg > 25
AND avg <= 50 THEN Name
END) AS _50,
COUNT(CASE
WHEN avg > 50
AND avg <= 75 THEN Name
END) AS _75,
COUNT(CASE
WHEN avg > 75
AND avg <= 100 THEN Name
END) AS _100
FROM
(
SELECT
EXTRACT(MONTH from Date) AS Month,
Name,
AVG(Percent) AS avg
FROM
table1
GROUP BY Month, Name, Group
HAVING Group = 'gr1'
) AS namegr
GROUP BY Month
This is the result:
Month
_25
_50
_75
_100
1
1
1
0
0
2
1
1
0
0
See also Fiddle (BUT on MySql) - http://sqlfiddle.com/#!9/16c5882/9
You can use this query to Group By Month and each Name
SELECT CONCAT(EXTRACT(MONTH FROM Date), ', ', Name) AS DateAndName,
CASE
WHEN AVG(Percent) <= 25 THEN '1'
ELSE '0'
END AS '<=25%',
CASE
WHEN AVG(Percent) > 25 AND AVG(Percent) <= 50 THEN '1'
ELSE '0'
END AS '25<_<=50%',
CASE
WHEN AVG(Percent) > 50 AND AVG(Percent) <= 75 THEN '1'
ELSE '0'
END AS '50<_<=75%',
CASE
WHEN AVG(Percent) > 75 AND AVG(Percent) <= 100 THEN '1'
ELSE '0'
END AS '75<_<=100%'
from DataTable /*change to your table name*/
group by EXTRACT(MONTH FROM Date), Name
order by DateAndName
It gives the following result:
DateAndName
<=25%
25<_<=50%
50<_<=75%
75<_<=100%
1, name1
1
0
0
0
1, name2
0
1
0
0
2, name1
1
0
0
0
2, name2
0
1
0
0

infuse a sum of the value in the another column with a different filter than the total count column

First here's a sample table.
enter image description here
Provider_name patient date status length
AF AGUIR00001 07/05/2018 3 30
AF ABBOT00001 07/05/2018 30
BB ADAMS00001 07/05/2018 3 30
BB ACEVE00001 07/06/2018 3 30
I have created a query that lets me count the total number of appointments versus the number of appointments with a certain status(eg checked out). I was able to create it and group it by provider.
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout
from appointment
group by provider_name
Then I moved on to the next phase which was to get the total length of those appointments with checkedout status. I made this query but it does not break down into each provider.
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
(select sum(length) from appointment where status = 3
and date between '06/01/2018' and '07/06/2018')
from appointment where date between '06/01/2018' and '07/06/2018'
group by provider_name
I need it so that the last column in the query is segregated per provider_name.
Thank you in advance for helping me out.
Actually, you were on the right way, try this:
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
sum(case when status = 3 then length else 0 end) as len_status3
from appointment
where date between '2018-01-06' and '2018-06-07'
group by provider_name;
According to your last comment, you need a WITH ROLLUP modifier for GROUP BY as in the following :
select coalesce(provider_name,'Total') as provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
sum(case when status = 3 then length else 0 end) as len_status3
from appointment
where date between '2018-01-06' and '2018-06-07'
group by provider_name with rollup;
SQL Fiddle Demo
you shoul do as for checkedoutout
select provider_name,
count(patient) total,
sum(case when status = 3 then 1 else 0 end) as Checkedout,
sum( case when status = 3 then length else 0 ) as total_length
from appointment where date between '06/01/2018' and '07/06/2018'
group by provider_name

Group by datepart and find total count of individual values of each record

This is table structure;
ID Score Valid CreatedDate
1 A 1 2018-02-19 23:33:10.297
2 C 0 2018-02-19 23:32:40.700
3 B 1 2018-02-19 23:32:30.247
4 A 1 2018-02-19 23:31:37.153
5 B 0 2018-02-19 23:25:08.667
...
I need to find total number of each score and valid in each month
I mean final result should be like
Month A B C D E Valid(1) NotValid(0)
January 123 343 1021 98 12 1287 480
February 516 421 321 441 421 987 672
...
This is what I tried;
SELECT DATEPART(year, CreatedDate) as Ay,
(select count(*) from TableResults where Score='A') as 'A',
(select count(*) from TableResults where Score='B') as 'B',
...
FROM TableResults
group by DATEPART(MONTH, CreatedDate)
but couldn't figure how to calculate all occurrence of scores on each month.
Use conditional aggregation.
SELECT DATEPART(year, CreatedDate) as YR
, DATEPART(month, CreatedDate) MO
, sum(Case when score = 'A' then 1 else 0 end) as A
, sum(Case when score = 'B' then 1 else 0 end) as B
, sum(Case when score = 'C' then 1 else 0 end) as C
, sum(Case when score = 'D' then 1 else 0 end) as D
, sum(Case when score = 'E' then 1 else 0 end) as E
, sum(case when valid = 1 then 1 else 0 end) as Valid
, sum(case when valid = 0 then 1 else 0 end) as NotValid
FROM TableResults
GROUP BY DATEPART(MONTH, CreatedDate), DATEPART(year, CreatedDate)
I'm not a big fan of queries in the select; I find they tend to cause performance problems in the long run. Since we're aggregating here I just applied the conditional logic to all the columns.

Select multiple COUNTs for every day

I got a table of Visitors.
Visitor has the following columns:
Id
StartTime (Date)
Purchased (bool)
Shipped (bool)
For each day within the last 7 days, I want to select 3 counts of the Visitors who have that day as StartTime:
The count of total visitors
The count of total visitors where Purchased = true
The count of total visitors where Shipped = true
Ideally the returned result would be:
Day Total TotalPurchased TotalShipped
1 100 67 42
2 82 61 27
etc...
I am used to .NET Linq so this has proved to be quite a challenge for me.
All I have come up with so far is the following:
SELECT COUNT(*) AS Total
FROM [dbo].[Visitors]
WHERE DAY([StartTime]) = DAY(GETDATE())
It selects the total of the current day just fine, however I feel pretty stuck right now so it'd be nice if someone could point me in the right direction.
For the last 7 days use the query proposed by Stanislav but with this WHERE clause
SELECT DAY([StartTime]) theDay,
COUNT(*) AS Tot,
SUM(CASE WHEN Purchased=true THEN 1 ELSE 0 END) as TotPurch,
SUM(CASE WHEN Shipped=true THEN 1 ELSE 0 END) as TotShip
FROM [dbo].[Visitors]
WHERE [StartTime] BETWEEN GETDATE()-7 AND GETDATE()
GROUP BY DAY([StartTime])
SELECT COUNT(*) AS Total,
SUM(CASE WHEN Purchased=true THEN 1 ELSE 0 END) as TotalPurchased,
SUM(CASE WHEN Shipped=true THEN 1 ELSE 0 END) as TotalShipped
FROM [dbo].[Visitors]
WHERE DAY([StartTime]) = DAY(GETDATE())
and add GROUP BY DAY([StartTime]) as jarlh mentioned
Here's a simple select that will give you the dataset you want
SELECT DATEDIFF(day,StartTime, getdate())+1 as [Day], -- Add 1 to display 1 to 7 instead of 0 to 6
COUNT(*) as Total,
SUM(CASE WHEN Purchased = 1 THEN 1 ELSE 0 END) as TotalPurchased,
SUM(CASE WHEN Shipped = 1 THEN 1 ELSE 0 END) AS TotalShipped
FROM Visitors
WHERE DATEDIFF(day,startTime,GETDATE()) < 6
GROUP BY DATEDIFF(day,startTime,GETDATE())
ORDER BY 1
This query will not take into consideration the time component of the date.

SQL - count occurrences in a column by DAY

I have a table as follows:
and I want to count the occurrences of say "ab" and "cd" in the column PageURL and GROUP by DAY (i.e. no matter how many occurrences for the day, it's count as 1).
ID User Activity PageURL ActDateTime
1 Me act1 abcd 2013-01-17 19:09:01.040
2 Me act2 cdab 2013-01-17 19:09:06.613
3 You act2 xyza 2013-01-30 16:10:50.177
4 Me act3 xyab 2013-01-30 10:35:09.037
I want to have 2 columns...1 for count of "ab" and 1 for count of "cd".
In the above example, there are 3 counts for "ab" but I will only count as 2 because the first 2 occurred on the SAME day (so count as 1).
Again, there are 2 counts for "cd" in PageURL column but I want to only count as 1 because occurred on same day too.
Furthermore, I want to group by Month-Year i.e. Jan-12, Feb-12, March-12, April-12 ...etc.
Would really appreciate some assistance and advice. Thank you!
This is what I've done so far (but it does NOT take into the account of grouping by DAY)
SELECT USER,
department,
activity,
[MonthYear] = DATENAME(mm, ActDateTime)+ ' - ' +
DATENAME(yy, actdatetime),
[ab] = sum(case when pageURL like '%ab%' THEN 1 else 0 END),
[cd]= sum(CASE WHEN pageURL LIKE '%cd%'THEN 1 ELSE 0 END)
FROM activityLog
GROUP BY USER,
department,
activity,
DATENAME(mm, ActDateTime)+ ' - ' +
DATENAME(yy, ActDateTime)
ORDER BY USER,
department,
activity,
DATENAME(mm, ActDateTime)+ ' - ' + DATENAME(yy, ActDateTime)
This should work to create your counts I think:
SELECT
cast(ActDateTime as Date) as DateOnly,
SUM(CASE WHEN PageUrl Like '%ab%' THEN 1 ELSE 0 END) as ABCount,
SUM(CASE WHEN PageUrl Like '%cd%' THEN 1 ELSE 0 END) as CDCount
FROM Table1
GROUP BY cast(ActDateTime as Date)
SQL Fiddle
First query to get counts by day:
SELECT cast(ActDateTime AS Date) AS DateOnly,
CASE
WHEN SUM(CASE WHEN PageUrl LIKE '%ab%' THEN 1 ELSE 0 END) >=1 THEN 1
ELSE 0
END AS ABCount,
CASE
WHEN SUM(CASE WHEN PageUrl LIKE '%cd%' THEN 1 ELSE 0 END) >=1 THEN 1
ELSE 0
END AS CDCount
FROM activityLog
GROUP BY cast(ActDateTime AS Date)
Second Query to get your desired output:
SQLFIDDLEExample
SELECT DATENAME(month, a.ActDateTime)+ ' - ' + DATENAME(yy, a.ActDateTime)
,SUM(a.ABCount) as ABCount
,SUM(a.CDCount) as CDCount
FROM (SELECT cast(ActDateTime AS Date) AS ActDateTime,
CASE
WHEN SUM(CASE WHEN PageUrl LIKE '%ab%' THEN 1 ELSE 0 END) >=1 THEN 1
ELSE 0
END AS ABCount,
CASE
WHEN SUM(CASE WHEN PageUrl LIKE '%cd%' THEN 1 ELSE 0 END) >=1 THEN 1
ELSE 0
END AS CDCount
FROM activityLog
GROUP BY cast(ActDateTime AS Date))a
GROUP BY DATENAME(month, a.ActDateTime)+ ' - ' + DATENAME(yy, a.actdatetime)
ORDER BY DATENAME(month, a.ActDateTime)+ ' - ' + DATENAME(yy, a.actdatetime)
Result:
| COLUMN_0 | ABCOUNT | CDCOUNT |
--------------------------------------
| January - 2013 | 2 | 1 |
SELECT Thing
,COUNT(*) NumDays
FROM (SELECT LEFT(PageURL, 2) AS Thing
,DateTime
FROM table
ALL
SELECT RIGHT(PageURL, 2)
,DateTime
FROM table) UniqueDays
This will not work as is because of the key words you have used in your question.
In general it is easier to use the actual column/table names so the answer can reflect these - it avoids confusion.