Select Criteria based on previous 5 days - sql

Table Name: INCLog
Table
UID Incident Number Modified Date Modified By
1 INC000011193511 2/18/2018 12:04 zuck
1 INC000011193511 2/19/2018 1:42 shei
1 INC000011193511 3/14/2018 5:08 byrr
1 INC000011193511 3/17/2018 5:08 byrr
2 INC000011193513 1/23/2018 2:58 r070
2 INC000011193513 1/27/2018 9:27 r070
2 INC000011193513 2/21/2018 5:42 gont
2 INC000011193513 3/16/2018 6:06 r070
3 INC000011193514 2/1/2018 6:07 shei
3 INC000011193514 2/13/2018 6:07 r070
4 INC000011193515 2/20/2018 21:05 moha
4 INC000011193515 2/21/2018 8:05 moha
4 INC000011193515 3/15/2018 18:34 doss
How do I use Select statement to return incident numbers modified in last 5 days?
For an instance; INC000011193511 was last modified on 3/17/2018, the query should return the entire log of the same ticket
1 INC000011193511 2/18/2018 12:04 zuck
1 INC000011193511 2/19/2018 1:42 shei
1 INC000011193511 3/14/2018 5:08 byrr
1 INC000011193511 3/17/2018 5:08 byrr
Thanks in advance for the help!

Find last modified date for each incident with max window function. Then compare with current date. Your query should be something like:
select
*
from (
select
*, mDate = max([modified date]) over (partition by [Incident Number])
from
myTable
) t
where
mDate >= dateadd(dd, -5, getdate())

If you want just last 5day transactions for specific transactions then you can use following query.
SELECT * FROM INCLog where IncedentNumber ='INC000011193511' AND ModifiedDate = DATEADD(DAY, - 5,GETDATE () )

I would recommend doing this as:
SELECT Incident_Number, MAX(Modified_Date) maxDate
FROM TempTabel
GROUP BY Incident_Number
HAVING MAX(Modified_Date)) > = dateadd(dd, -5, getdate())
Thank You!

If i understand correctly you could use group by clause to find the max date of each Incident number and compare it with last 5 days
SELECT t.* FROM table t
CROSS APPLY (
SELECT Incident, MAX([Modified Date]) Mdate FROM table
WHERE Incident = t.Incident
GROUP BY Incident) c
WHERE c.Mdate >= DATEADD(DD, -5 , getdate())

Related

How to select weekly data from daily data

There are two columns, XCHG_DATE and USD_KRW, and the table contains daily data.
What I am trying to do is to select weekly data from the daily data.
E.g) (2022-03-01, value), (2022-03-08, value), (2022-03-15, value), (2022-03-22, value) and so one...
The current SQL I have is:
SELECT CE.XCHG_DATE xchageDate
, CE.USD_KRW usdKrw
FROM(
SELECT DATEADD(WEEK, DATEDIFF(WEEK, 1, XCHG_DATE), 4) xchageDate
FROM CWL_EXCHANGE
WHERE XCHG_DATE BETWEEN '20220301' AND '20220523'
GROUP BY DATEADD(WEEK, DATEDIFF(WEEK, 1, XCHG_DATE),4)
) AS RESULT
LEFT JOIN CWL_EXCHANGE CE
ON CE.XCHG_DATE = RESULT.xchageDate
WHERE RESULT.xchageDate = CE.XCHG_DATE
ORDER BY CE.XCHG_DATE;
This query gives me weekly data from 20220304 to 20220520, but I need the data from 2022-03 to 2022-05-23(today's date).
Can anyone please help me of how to solve this problem?
Thanks in advance!
Sample Data:
COLUMNS = XCHG_DATE USD_KRW
2022-05-23 1
2022-05-22 2
2022-05-21 3
2022-05-20 4
2022-05-19 5
2022-05-18 6
2022-05-17 7
2022-05-16 8
2022-05-15 9
2022-05-14 10
2022-05-13 11
2022-05-12 12
2022-05-11 13
2022-05-10 14
2022-05-09 15
2022-05-08 16
2022-05-07 17
2022-05-06 18
Current Output :
20220506 18
20220513 11
20220520 4
Expected Output :
20220509 15
20220516 8
20220523 1
You will need a calendar table with Weekdaynumber to arrive at the earlier weekdays corresponding to Today's date(23 May 2022). This will make the calculation easier.
DECLARE #StartDate DATE = '2022-05-01'
DECLARE #EndDate DATE = '2022-05-31'
declare #table table (XCHG_DATE date, USD_KRW int);
insert into #table
values ('2022-05-23', 1 )
,('2022-05-22', 2 )
,('2022-05-21', 3 )
,('2022-05-20', 4 )
,('2022-05-19', 5 )
,('2022-05-18', 6 )
,('2022-05-17', 7 )
,('2022-05-16', 8 )
,('2022-05-15', 9 )
,('2022-05-14', 10 )
,('2022-05-13', 11 )
,('2022-05-12', 12 )
,('2022-05-11', 13 )
,('2022-05-10', 14 )
,('2022-05-09', 15 )
,('2022-05-08', 16 )
,('2022-05-07', 17 )
,('2022-05-06', 18 );
;WITH Cal(n) AS
(
SELECT 0 UNION ALL SELECT n + 1 FROM Cal
WHERE n < DATEDIFF(DAY, #StartDate, #EndDate)
),
FnlDt(d,weeknum) AS
(
SELECT DATEADD(DAY, n, #StartDate),datepart(dw, DATEADD(DAY, n, #StartDate)) as weeknum FROM Cal
)
SELECT t.XCHG_DATE,t.USD_KRW
from FnlDt as c
INNER JOIN #table as t
on t.XCHG_DATE = c.d
where c.weeknum = datepart(dw, getdate()) -- Weekdaynumber today
XCHG_DATE
USD_KRW
2022-05-23
1
2022-05-16
8
2022-05-09
15
Sub in GETDATE() for the hardcoded value if you always want todays date
SELECT *
FROM CWL_EXCHANGE
WHERE DATEPART(dw, XCHG_DATE) = DATEPART(dw, '20220523')

SQL query group by using day startdatetime and end datetime

I have the following table Jobs:
|Id | StartDateTime | EndDateTime
+----+---------------------+----------------------
|1 | 2020-10-20 23:00:00 | 2020-10-21 05:00:00
|2 | 2020-10-21 10:00:00 | 2020-10-21 11:00:00
Note job id 1 spans October 20 and 21.
I am using the following query
SELECT DAY(StartDateTime), COUNT(id)
FROM Job
GROUP BY DAY(StartDateTime)
To get the following output. But the problem I am facing is that day 21 is not including job id 1. Since the job spans two days I want to include it in both days 20 and 21.
Day | TotalJobs
----+----------
20 | 1
21 | 1
I am struggling to get the following expected output:
Day | TotalJobs
----+----------
20 | 1
21 | 2
One method is to generate the days that you want and then count overlaps:
with days as (
select convert(date, min(j.startdatetime)) as startd,
convert(date, max(j.enddatetime)) as endd
from jobs j
union all
select dateadd(day, 1, startd), endd
from days
where startd < endd
)
select days.startd, count(j.id)
from days left join
jobs j
on j.startdatetime < dateadd(day, 1, startd) and
j.enddatetime >= startd
group by days.startd;
Here is a db<>fiddle.
You can first group by with same start and end date and then group by for start and end date having different start and end date
SELECT a.date, SUM(counts) from (
SELECT DAY(StartDateTime) as date, COUNT(id) counts
FROM Table1
WHERE DAY(StartDateTime) = DAY(EndDateTime)
GROUP BY StartDateTime
UNION ALL
SELECT DAY(EndDateTime), COUNT(id)
FROM Table1
WHERE DAY(StartDateTime) != DAY(EndDateTime)
GROUP BY EndDateTime
UNION ALL
SELECT DAY(StartDateTime), COUNT(id)
FROM Table1
WHERE DAY(StartDateTime) != DAY(EndDateTime)
GROUP BY StartDateTime) a
GROUP BY a.date
Here is SQL Fiddle link
SQL Fiddle
Also replace Table1 with Jobs when running over your db context

Count distinct records but only 1 time every XX Days

EDIT: Start date as of Jan 1 XXXX
I need to create a count of distinct userID's based on a 7 day grouping. Basically if a User calls on day 1 and day 2 of the month, they are counted 1 time. However if they call on Day 1 and day 10, then they are counted 2 times.
Table layout:
userId CallId datetime
0 123 01/01/2016 xx:xx:xx
0 124 01/10/2016 xx:xx:xx
1 125 01/10/2016 xx:xx:xx
1 126 01/10/2016 xx:xx:xx
2 127 01/10/2016 xx:xx:xx
1 128 01/30/2016 xx:xx:xx
2 129 01/31/2016 xx:xx:xx
What I need the return to look like:
Count(UserID) Week#
1 1
3 2
2 4
Thank you for your time.
Based on Gurwinders response I have produced the following and included years so that it is still usuable in a years time.
SELECT COUNT(UserID), CallYear, CallWeek
FROM (
SELECT DISTINCT UserID,
datepart(year,datetime) as CallYear,
datepart(week,datetime) as CallWeek
FROM my_table
)
Group By CallYear,CallWeek
This will produce a rolling distinct count begining Jan 1
Declare #YourTable table (userId int,CallId int,datetime datetime)
Insert Into #YourTable values
(0,123,'2016-01-01'),
(0,124,'2016-01-10'),
(1,125,'2016-01-10'),
(1,126,'2016-01-10'),
(2,127,'2016-01-10'),
(1,128,'2016-01-30'),
(2,129,'2016-01-31')
Select D1
,D1 =DateAdd(DD,6,D1)
,Cnt=count(Distinct UserID)
From #YourTable A
Join (Select Top 500 D1=DateAdd(DD,(Row_Number() Over (Order By Number)-1)*7,'2016-01-01') From master..spt_values ) B
on datetime between D1 and DateAdd(DD,6,D1)
Group By D1
Returns
D1 D1 Cnt
2016-01-01 2016-01-07 1
2016-01-08 2016-01-14 3
2016-01-29 2016-02-04 2
you can use this:
select count(distinct userid), datepart(week, datetime) week, datepart(year, datetime) year
from my_table
group by datepart(week, datetime), datepart(year, datetime);
What is your starting date? Have you looked at the DateDiff() function?
Try this:
With ABC
As
(select datepart(week, datetime) as week#
from table)
Select count(week#) as Times,week#
From ABC

SQL count number of users every 7 days

I am new to SQL and I need to find count of users every 7 days. I have a table with users for every single day starting from April 2015 up until now:
...
2015-05-16 00:00
2015-05-16 00:00
2015-05-17 00:00
2015-05-17 00:00
2015-05-17 00:00
2015-05-17 00:00
2015-05-17 00:00
2015-05-18 00:00
2015-05-18 00:00
...
and I need to count the number of users every 7 days (weekly) so I have data weekly.
SELECT COUNT(user_id), Activity_Date FROM TABLE_NAME
I need output like this:
TotalUsers week1 week2 week3 ..........and so on
82 80 14 16
I am using DB Visualizer to query Oracle database.
You should try following,
Select
sum(Week1) + sum(Week2) + sum(Week3) + sum(Week4) + sum(Week5) as Total,
sum(Week1) as Week1,
sum(Week2) as Week2,
sum(Week3) as Week3,
sum(Week4) as Week4,
sum(Week5) as Week5
From (
select
case when week = 1 then 1 else 0 end as Week1,
case when week = 2 then 1 else 0 end as Week2,
case when week = 3 then 1 else 0 end as Week3,
case when week = 4 then 1 else 0 end as Week4,
case when week = 5 then 1 else 0 end as Week5
from
(
Select
CEILING(datepart(dd,visitdate)/7+1) week,
user_id
from visitor
)T
)D
Here is Fiddle
You need to add month & year in the result as well.
SELECT COUNT(user_id), Activity_Date FROM TABLE_NAME WHERE Activity_Date > '2015-06-31';
That would get the amount of users for the last 7 days.
This is my test table:
user_id act_date
1 01/04/2015
2 01/04/2015
3 04/04/2015
4 05/04/2015
..
This is my query:
select week_offset, count(*) nb from (
select trunc((act_date-to_date('01042015','DDMMYYYY'))/7) as week_offset from test_date)
group by week_offset
order by 1
and this is the output:
week_offset nb
0 6
1 3
4 5
5 7
6 3
7 1
18 1
Week offset is the number of the week from 01/04/2015, and we can show the first day of the week.
See here for live testing.
How do you define your weeks? Here's an approach for SQL Server that starts each seven-day block relative to the start of April. The expressions will vary according to your specific needs:
select
dateadd(
dd,
datediff(dd, cast('20150401' as date), Activity_Date) / 7 * 7,
cast('20150401' as date)
) as WeekStart,
count(*)
from T
group by datediff(dd, cast('20150401' as date), Activity_Date) / 7
Oracle:
select
trunc(Activity_date, 'DAY') as WeekStart,
count(*)
from T
group by trunc(Activity_date, 'DAY') /* D and DAY are the same thing */

SQL Server : Gap / Island, datetime, contiguous block 365 day block

I have a table that looks like this:-
tblMeterReadings
id meter period_start period_end amount
1 1 2014-01-01 00:00 2014-01-01 00:29:59 100.3
2 1 2014-01-01 00:30 2014-01-01 00:59:59 50.5
3 1 2014-01-01 01:00 2014-01-01 01:29:59 70.7
4 1 2014-01-01 01:30 2014-01-01 01:59:59 900.1
5 1 2014-01-01 02:00 2014-01-01 02:29:59 400.0
6 1 2014-01-01 02:30 2014-01-01 02:59:59 200.3
7 1 2014-01-01 03:00 2014-01-01 03:29:59 100.8
8 1 2014-01-01 03:30 2014-01-01 03:59:59 140.3
This is a tiny "contiguous block" from '2014-01-01 00:00' to '2014-01-01 3:59:59'.
In the real table there are "contiguous blocks" of years in length.
I need to find the the period_start and period_end of the most recent CONTINUOUS 365 COMPLETE DAYs (fileterd by meter column).
When I say COMPLETE DAYs I mean a day that has entries spanning 00:00 to 23:59.
When I say CONTINUOUS I mean there must be no days missing.
I would like to select all the rows that make up this block of CONTINUOUS COMPLETE DAYs.
I also need an output like:
block_start block_end total_amount_for_block
2013-02-26 00:00 2014-02-26 23:59:59 1034234.5
This is beyond me, so if someone can solve... I will be very impressed.
Since your granularity is 1 second, you need to expand your periods into all the date/times between the start and end at 1 second intervals. To do this you need to cross join with a numbers table (The numbers table is generated on the fly by ranking object ids from an arbitrary system view, I have limited it to TOP 86400 since this is the number of seconds in a day, and you have stated your time periods never span more than one day):
WITH Numbers AS
( SELECT TOP (86400)
Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
ORDER BY a.object_id
)
SELECT r.ID, r.meter, dt.[DateTime]
FROM tblMeterReadings r
CROSS JOIN Numbers n
OUTER APPLY
( SELECT [DateTime] = DATEADD(SECOND, n.Number, r.period_start)
) dt
WHERE dt.[DateTime] <= r.Period_End;
You then have your continuous range in which to perform the normal gaps and islands grouping:
WITH Numbers AS
( SELECT TOP (86400)
Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
FROM sys.all_objects a
CROSS JOIN sys.all_objects b
ORDER BY a.object_id
), Grouped AS
( SELECT r.meter,
Amount = CASE WHEN Number = 1 THEN r.Amount ELSE 0 END,
dt.[DateTime],
GroupingSet = DATEADD(SECOND,
-DENSE_RANK() OVER(PARTITION BY r.Meter
ORDER BY dt.[DateTime]),
dt.[DateTime])
FROM tblMeterReadings r
CROSS JOIN Numbers n
OUTER APPLY
( SELECT [DateTime] = DATEADD(SECOND, n.Number, r.period_start)
) dt
WHERE dt.[DateTime] <= r.Period_End
)
SELECT meter,
PeriodStart = MIN([DateTime]),
PeriodEnd = MAX([DateTime]),
Amount = SUM(Amount)
FROM Grouped
GROUP BY meter, GroupingSet
HAVING DATEADD(YEAR, 1, MIN([DateTime])) < MAX([DateTime]);
N.B. Since the join to Number causes amounts to be duplicated, it is necessary to set all duplicates to 0 using CASE WHEN Number = 1 THEN r.Amount ELSE 0 END, i.e only include the amount for the first row for each ID
Removing the Having clause for your sample data will give:
meter | PeriodStart | PeriodEnd | Amount
------+---------------------+---------------------+----------
1 | 2014-01-01 00:00:00 | 2014-01-01 03:59:59 | 1963
Example on SQL Fiddle
You could try this:
Select MIN(period_start) as "block start"
, MAX(period_end) as "block end"
, SUM(amount) as "total amount"
FROM YourTable
GROUP BY datepart(year, period_start)
, datepart(month, period_start)
, datepart(day, period_start)
, datepart(year, period_end)
, datepart(month, period_end)
, datepart(day, period_end)
Having datepart(year, period_start) = datepart(year, period_end)
AND datepart(month, period_start) = datepart(month, period_end)
AND datepart(day, period_start) = datepart(day, period_end)
AND datepart(hour, MIN(period_start)) = 0
AND datepart(minute,MIN(period_start)) = 0
AND datepart(hour, MAX(period_end)) = 23
AND datepart(minute,MIN(period_end)) = 59