SQL - count occurrences in a column by DAY - sql

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.

Related

how to sum two column within single case statement

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);

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 entries per week where each column got specific date validation

I am trying to group tickets per week in a year when data field X are between that week. The final result should be something like Week,Datefield1,Datefield2..
What I reached so far:
DECLARE #YearStartDate datetime
SET #YearStartDate = '2016-01-04 00:00:00.000'
DECLARE #YearEndDate datetime
SET #YearEndDate = '2016-04-24 00:00:00.000'
SELECT
Year(T.CreateDate) as 'Year',
'Week ' + cast(datepart(wk, CreateDate) as varchar(2)) as 'Week',
Sum(CASE WHEN CreateDate BETWEEN #YearStartDate and #YearEndDate
THEN 1 Else 0 End) 'Created'
FROM mytable AS T
GROUP BY Year(T.CreateDate),datepart(wk,T.CreateDate)
ORDER BY Year(T.CreateDate),datepart(wk, T.CreateDate)
Result:
Year Week Created
----------- ------- -----------
2016 Week 1 0
2016 Week 2 5
2016 Week 3 3
2016 Week 4 2
Goal:
Year Week Created Schuduled Closed
----------- ------- ----------- ----------- -----------
2016 Week 1 0 0 0
2016 Week 2 5 3 2
2016 Week 3 3 2 2
2016 Week 4 2 2 0
Suggestion?
SELECT
Year(..) as 'Year',
'Week ' + cast(datepart(wk, ...) as varchar(2)) as 'Week',
Sum(CASE WHEN CreateDate BETWEEN #YearStartDate and #YearEndDate
THEN 1 Else 0 End) 'Created'
Sum(CASE WHEN ScheduledDate BETWEEN #YearStartDate and #YearEndDate
THEN 1 Else 0 End) 'Scheduled'
Sum(CASE WHEN ClosedDate BETWEEN #YearStartDate and #YearEndDate
THEN 1 Else 0 End) 'Closed'
FROM mytable AS T
GROUP BY Year(...)
ORDER BY Year(...)
Constraints:
I can count the entries per week for one datafield but for several datafields (created,scheduled,pending,closed) I think I need to change the logic. Maybe create a inner join or left join against the same table.
I was wondering if you could give me some guidance on finding the right path. Thanks for taking the time to help me.
All the best.
Right, join on other similar SELECTs for scheduled and closed should work. Something as
DECLARE #YearStartDate datetime = '2016-01-04 00:00:00.000';
DECLARE #YearEndDate datetime = '2016-04-24 00:00:00.000';
SELECT CLR.*, SCH.Schuduled, CLS.Closed FROM
(SELECT
Year(T.CreateDate) as 'Year',
'Week ' + cast(datepart(wk, CreateDate) as varchar(2)) as 'Week',
Sum(CASE WHEN CreateDate BETWEEN #YearStartDate and #YearEndDate THEN 1 Else 0 End) 'Created'
FROM mytable AS T
GROUP BY Year(T.CreateDate),datepart(wk,T.CreateDate)
) CRT
JOIN
(SELECT
Year(T.ScheduleDate) as 'Year',
'Week ' + cast(datepart(wk, ScheduleDate) as varchar(2)) as 'Week',
Sum(CASE WHEN ScheduleDate BETWEEN #YearStartDate and #YearEndDate THEN 1 Else 0 End) 'Schuduled'
FROM mytable AS T
GROUP BY Year(T.ScheduleDate),datepart(wk,T.ScheduleDate)
) SCH
ON CRT.Year = SCH.Year
AND CRT.Week = SCH.Week
JOIN
(SELECT
Year(T.ClosedDate) as 'Year',
'Week ' + cast(datepart(wk, ClosedDate) as varchar(2)) as 'Week',
Sum(CASE WHEN ClosedDate BETWEEN ClosedDate and #YearEndDate THEN 1 Else 0 End) 'Closed'
FROM mytable AS T
GROUP BY Year(T.ClosedDate),datepart(wk,T.ClosedDate)
) CLS
ON CRT.Year = CLS.Year
AND CRT.Week = CLS.Week
ORDER BY Year, Week
You have three different date columns. One method would pre-aggregation along the dimensions and then use full outer join. Alternatively, you can use union all and aggregation:
SELECT Year(dte) as [Year],
'Week ' + datename(wk, dte) as [Week],
Sum(Created) as Created,
Sum(Scheduled) as Scheduled,
Sum(Closed) as Closed
FROM ((SELECT createddate as dte, 1 as created, 0 as schedule, 0 as closed
FROM mytable
) UNION ALL
(SELECT scheduleddate as dte, 0 as created, 1 as schedule, 0 as closed
FROM mytable
) UNION ALL
(SELECT closeddate as date, 1 as created, 0 as schedule, 0 as closed
FROM mytable
)
) t
GROUP BY Year(date), datename(wk, dte)
ORDER BY Year(date), datename(wk, dte);
I would encourage a couple of things:
Do not use single quotes for column aliases. Only use single quotes for string and date names.
Do not use reserved works such as "year" for column or table names.
Also note the use of datename(). This returns a string so no conversion is needed.

Group by year in sql

I am trying to group by year but was not able to do.I can get the column count but not year wise. this is what i tried.
select t_contract ,
sum(CASE t_contract when '18' then 1 else 0 end) as XL,
sum(CASE t_contract when '01' then 1 else 0 end) as VC,
sum(CASE t_contract when '75' then 1 else 0 end) as AN,
sum(CASE t_contract when '48' then 1 else 0 end) as CS
from icps.dbo.tickets
WHERE
t_date_time_issued >= DATEADD(year, -6, GETDATE())
GROUP BY contract
.. but i want to add year .. where i have t_date_time _issued column.
My another query is I have a column called t_zone_name and I want to sum all the rows where t_zone_anme like '%ICeland%' an i tried this:
sum(CASE t_zone_name like '%ICeland%' then 1 else 0 end) as ICELAND
but I get an error on statement like... thanks in advance.
LIKE
YEAR XL VC AN CS total
2010 50 50 50 50 200
2011 5 5 5 5 20
Try the below query:
SELECT t_contract, YEAR(t_date_time_issued) As Yr, SUM(CASE WHEN t_zone_name like '%ICeland%' THEN 1 ELSE 0 END) AS ICELAND
SUM(CASE t_contract when '18' then 1 else 0 end) as XL,
SUM(CASE t_contract when '01' then 1 else 0 end) as VC,
SUM(CASE t_contract when '75' then 1 else 0 end) as AN,
SUM(CASE t_contract when '48' then 1 else 0 end) as CS
FROM icps.dbo.tickets
WHERE YEAR(t_date_time_issued) >= (YEAR(GetDate()) - 6)
GROUP BY t_contract, YEAR(t_date_time_issued)
You might need change the order of t_contract and YEAR(t_date_time_issued) depending on which grouping you want to apply first.
As suggested by #ray I have replaced DATEPART(yyyy, t_date_time_issued) >= DATEPART(yyyy, DATEADD(year, -6, GETDATE())) with year(t_date_time_issued) >= (year(GetDate()) - 6)
If you want to group by year, in sql server, you might
GROUP BY DATEDIFF(year,t_date_time_issued, GETDATE())
In other DB engine, usually has method to get year part, or use substring to get year part from a time string.

How to show different dates data (from the same table) as columns in Oracle

I'm sorry if the title wasn't too clear, but the following explanation will be more accurate.
I have the following view:
DATE USER CONDITION
20140101 1 A
20140101 2 B
20140101 3 C
20140108 1 C
20140108 3 B
20140108 2 C
What I need to do is present how many users where in all conditions this week and 7 days before today.
Output should be like this:
Condition Today Last_Week (Today-7)
A 0 1
B 1 1
C 2 1
How can I do this in Oracle? I will need to do this for 4 weeks so itll be Today-7,14-21.
I've tried this with group by but I get the "week2" as rows. Then I've tried something like Select conditions, (select count(users) from MyView where DATE='Today') FROM MyView(looking at something thats actually working) but it doesnt work for me.
Achieved this with a little modification of the accepted answer:
select condition,
count(case when to_date(xdate) = to_date(sysdate) then 1 end) to_day,
count(case when to_date(xdate) = to_date(sysdate-7) then 1 end) last_7_days
from my_table
group by condition
select condition, count(case when to_date(xdate) = to_date(sysdate) then 1 end) to_day,
count(case when to_date(xdate) < to_date(sysdate) then 1 end) last_7_days
from my_table
where to_date(xdate) >= to_date(sysdate) - 7
group by condition
select condition
, sum
( case
when date between trunc(sysdate) - 7 and trunc(sysdate) - 1
then 1
else 0
end
)
last_week
, sum
( case
when date between trunc(sysdate) and trunc(sysdate + 1)
then 1
else 0
end
)
this_week
from table
group
by condition
By using the conditional count (as a sum) and grouping on condition you can filter out all desired dates. Note that using trunc will cause to use the begin of the day.