Sum all the repeat event based on dates, aggregate by 7 days ,30 days >30 days - sql

I am trying to calculate repeat if there is a repeat event in 3,7,30 and >30 days.
In the image below the the yellow is the sql table,
the green is transformation needed, where I find out what is the first event for Event A and Event B. and then find out what is the gap between the first event of A and next events of A.
Finally I need to aggregate and achieve the blue table where data is aggregate for the unique events.
I have been trying to achieve this in SQL but I am stuck as I am not sure how to filter and loop.
Original data and Expected outcome image

DECLARE #reference_date DATE = '2022-08-02';
SELECT
Event,
MIN(Date) as First_date,
SUM(CASE WHEN DATEDIFF(day, #reference_date, Date) BETWEEN 1 AND 2
THEN 1 ELSE 0 END) as "Within_3_Days",
SUM(CASE WHEN DATEDIFF(day, #reference_date, Date) BETWEEN 1 AND 6
THEN 1 ELSE 0 END) as "Within_7_Days",
SUM(CASE WHEN DATEDIFF(day, #reference_date, Date) BETWEEN 1 AND 29
THEN 1 ELSE 0 END) as "Within_30_Days",
SUM(CASE WHEN DATEDIFF(day, #reference_date, Date)>=30
THEN 1 ELSE 0 END) as ">_30_Days"
FROM event e0
GROUP BY Event
output:
Event
First_date
Within_3_Days
Within_7_Days
Within_30_Days
>_30_Days
A
2022-08-01
0
1
2
1
B
2022-09-15
0
0
0
1
The #reference_date is used to reference the date needed to determine if a date is within x days.
DBFIDDLE
P.S. I use dates in the format YYYY-MM-DD, because that's the only way I am SURE about the ordering of the Day and the Month part.
EDIT:
When using the first date of an event to determine the 'within' columns, you can do:
SELECT
e0.Event,
MIN(e0.Date) as First_date,
SUM(CASE WHEN DATEDIFF(day, e1.Date, e0.Date) BETWEEN 1 AND 2
THEN 1 ELSE 0 END) as "Within_3_Days",
SUM(CASE WHEN DATEDIFF(day, e1.Date, e0.Date) BETWEEN 1 AND 6
THEN 1 ELSE 0 END) as "Within_7_Days",
SUM(CASE WHEN DATEDIFF(day, e1.Date, e0.Date) BETWEEN 1 AND 29
THEN 1 ELSE 0 END) as "Within_30_Days",
SUM(CASE WHEN DATEDIFF(day, e1.Date, e0.Date)>=30
THEN 1 ELSE 0 END) as ">_30_Days"
FROM event e0
INNER JOIN (SELECT Event,MIN(Date) as Date from event GROUP BY Event) e1 on e1.Event=e0.Event
GROUP BY e0.Event
see: DBFIDDLE2

Related

Issue on Count of total calls

On a 'CALLS' table each call has a call_start, contact_id, operator_id and so on.
I want to count the tot calls for each client on a specific weekday so I extract weekday (extract weekday from call_start) and I get 0 to 6 results.
I used a case to show weekdays (case when (extract(weekday from call_start)=1) then 'monday' and so on.
Now I enter count( client_id) and I get 2 row for 2 calls, 4 rows for 4 calls, rather than 1 row with 2 calls?
Am I missing something silly here?
I am using Firebird 1.5 by the way
u can try something like this
select
sum(case when extract(weekday from cast(call_start as date))=0 then 1 else 0 end) as qty_sun,
sum(case when extract(weekday from cast(call_start as date))=1 then 1 else 0 end) as qty_mon,
sum(case when extract(weekday from cast(call_start as date))=2 then 1 else 0 end) as qty_tue,
....

How to count different data on the basis of date for distinct users in SQL Server

I have the following schema :
Table T
|ITEM_ID| |USER_ID| | DUE_DATE |
1 1 2018-01-2
1 1 2018-01-2
1 1 2018-01-3
1 2 2018-01-2
2 1 2018-01-2
2 2 2018-01-2
What I want is to get the count of actions performed by a unique user on that particular day, one week.
This is the select query which I'm using however it does not takes care of the fact about unique user.
select ITEM_ID,
sum(case when cast(due_date as date) = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when cast(due_date as date) >= cast(getdate() - 7 as date) then 1 else 0 end) as week,
sum(case when cast(due_date as date) >= dateadd(month, -1, cast(getdate() as date)) then 1 else 0 end) as month
from t
group by ITEM_ID;
How can I the select count of actions performed by a unique user on that particular day, one week.
For example : let's suppose today is 2018-01-2
So the expected result should be :
ITEM_ID, COUNT_TODAY, COUNT_TOMORROW
1 2 1
2 1 1
What I need is the unique user performing the transaction of that particular item type for that day.
That is in the above example, the user having id 1 performed the transaction of type 1 2 times on 2018-01-2. So it should be counted as 1 instead of 2.
How can I achieve this?
Is this what you want.
select USER_ID, ITEM_ID,
sum(case when cast(due_date as date) = cast(getdate() as date) then 1 else 0 end) as today,
sum(case when cast(due_date as date) >= cast(getdate() - 7 as date) then 1 else 0 end) as week,
sum(case when cast(due_date as date) >= dateadd(month, -1, cast(getdate() as date)) then 1 else 0 end) as month
from t
group by USER_ID, ITEM_ID;

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.

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.

SQL Server - Pivot: Counting/Reporting number of records insert in 100 Staging Tables

We currently got 100 staging tables which are loaded everyday.
I'm struggling to write a query - which give me sort PIVOT result - showing number of records inserted into staging tables by Day.
Name of tables Day 1 Day 2 Day 3 Day 4 Day 5
--------------------------------------------------------------
AAAAA 100 50 30 60 90
Regards
You need a few different steps.
DATEDIFF(DAY, <timestamp>, getDate()) will get you the number of days ago for a record.
Using CASE inside a SUM, you can then do something like...
SELECT
'AAAA' AS TableName,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 1 THEN 1 ELSE 0 END) AS Day1,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 2 THEN 1 ELSE 0 END) AS Day2,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 3 THEN 1 ELSE 0 END) AS Day3,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 4 THEN 1 ELSE 0 END) AS Day4,
etc, etc
FROM
AAAA
UNION ALL
SELECT
'BBBB' AS TableName,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 1 THEN 1 ELSE 0 END) AS Day1,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 2 THEN 1 ELSE 0 END) AS Day2,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 3 THEN 1 ELSE 0 END) AS Day3,
SUM(CASE WHEN DATEDIFF(DAY, <timestamp>, getDate()) = 4 THEN 1 ELSE 0 END) AS Day4,
etc, etc
FROM
BBBB
UNION ALL
etc, etc
That does require the code repeating itself for every table you are querying. But I think you're stuck doing that in one way or another no matter what.
An alternative would be to put a trigger on each table, and as data is inserted/deleted, update a tracking table with the new details. That involves writing 100 triggers instead of 100 unions.
Without writing Dynamic SQL, I'm not aware of any other fundamentally different ways of doing this to aboid writing a snippet of code 100 times...