How to select weekly data from daily data - sql

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

Related

How to populate missing date row with next date row in sql server?

date value
01-01-2020 2
04-01-2020 3
05-01-2020 5
06-01-2020 7
05-01-2020 9
I want output:
date value
01-01-2020 2
02-01-2020 3
03-01-2020 3
04-01-2020 3
05-01-2020 5
06-01-2020 7
07-01-2020 9
08-01-2020 9
09-01-2020 9
10-01-2020 9
WITH cte1 AS
(
SELECT *,
lead(date) OVER (ORDER BY date) AS NextDate FROM Screen1
)
SELECT
c.Date,
t.value
FROM Calender1 c
JOIN cte1 t ON c.Date
BETWEEN t.date AND ISNULL(DATEADD(day, -1, t.NextDate), t.date)
I have tried this but its duplicating the previous date value.In this query i have used a calender table and joined that table with main table which has missing dates.
First you need to have calendar table. Then you can find the next available value using CROSS APPLY and fill that value.
declare #table table(dateval date, val int)
insert into #table
values
('2020-01-01', 2),
('2020-01-04', 3 ),
('2020-01-05', 5 ),
('2020-01-06', 7 ),
('2020-01-10', 9)
DECLARE #StartDate DATE = '2020-01-01'
DECLARE #EndDate DATE = '2020-01-31'
;WITH Cal(n) AS
(
SELECT 0 UNION ALL SELECT n + 1 FROM Cal
WHERE n < DATEDIFF(DAY, #StartDate, #EndDate)
),
FnlDt(d) AS
(
SELECT DATEADD(DAY, n, #StartDate) FROM Cal
)
SELECT f.d, t.val
FROM FnlDt as f
CROSS APPLY
(select top 1 val from
#table as t
where t.dateval >= f.d
order by t.dateval) as t(val)
d
val
2020-01-01
2
2020-01-02
3
2020-01-03
3
2020-01-04
3
2020-01-05
5
2020-01-06
7
2020-01-07
9
2020-01-08
9
2020-01-09
9
2020-01-10
9

Get previous month date values from data stored within SQL Server table

My table structure in SQL Server looks as below.
id startdate enddate value
---------------------------------------
1 2019-02-06 2019-02-07 11
1 2019-01-22 2019-02-05 10
1 2019-01-15 2019-01-21 14
1 2018-12-13 2018-01-14 15
1 2018-12-09 2018-12-12 14
1 2018-08-13 2018-12-08 17
1 2018-07-19 2018-08-12 19
1 2018-06-13 2018-07-18 20
Now my query needs to display value from highest start date for that month. Which is fine and I know what needs to be done but Not start just highest date value for that month, if no value is there for that start date, we carry forward value from last month. So basically if you notice on above data, after December 2018 values, there are no values for November, October, September etc but I want to return MM/YYYY values for that month in result but value for those months should be what we found on earlier month which is August values which in this example is 17. Please note that enddate will always be as of one day before new start date begins. Probably that can be used for back filling and carry forwarding missing month values?
So my result should look like below.
id date value
----------------------------
1 2019-02 11
1 2019-01 10
1 2018-12 15
1 2018-11 17
1 2018-10 17
1 2018-09 17
1 2018-08 17
1 2018-07 19
1 2018-06 20
Do you think this can be done without using cursor here?
Alexander Volok's answer is solid, so I won't go into too much extra code. But I thought I'd explain the reasoning. In essence, what you need to do is create a skeleton date table containing all the dates and primary keys you want returned. I'm guessing you have more than one id value in your real data, so probably something like this (whether you choose to persist it or not is up to you)
create table #skelly
(
id int,
_year int,
_month int
primary key (id, _year, _month)
)
You can get much more precise if you need to be, by only including dates which fall between the min and max StartDate per id, but that's an exercise I leave up to you.
From there, it's then just a matter of filling in the values you care about against that skeleton table. You can do this in a number of ways; by joining, cross applying or a correlated subquery (as Alexander Volok used).
DECLARE #start DATE, #end DATE;
SELECT #start = '20180601', #end = GETDATE();
;WITH Months AS
(
SELECT EOMONTH(DATEADD(month, n-1, #start)) AS DateValue FROM (
SELECT TOP (DATEDIFF(MONTH, #start, #end) + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects
) D
)
, InputData AS
(
SELECT 1 AS id, '2019-02-06' startdate, '2019-02-07' as enddate, 11 AS [value] UNION ALL
SELECT 1, '2019-01-22', '2019-01-25', 10 UNION ALL
SELECT 1, '2019-01-15', '2019-01-17', 14 UNION ALL
SELECT 1, '2018-12-13', '2018-12-19', 15 UNION ALL
SELECT 1, '2018-12-09', '2018-12-10', 14 UNION ALL
SELECT 1, '2018-08-13', '2018-12-08', 17 UNION ALL
SELECT 1, '2018-07-19', '2018-07-25', 19 UNION ALL
SELECT 1, '2018-06-13', '2018-07-18', 20
)
SELECT FORMAT(m.DateValue, 'yyyy-MM') AS [Month]
, (SELECT TOP 1 I.value FROM InputData I WHERE I.startdate < M.DateValue ORDER BY I.startdate DESC ) [Value]
FROM months m
ORDER BY M.DateValue DESC
Results to:
Month Value
2019-02 11
2019-01 10
2018-12 15
2018-11 17
2018-10 17
2018-09 17
2018-08 17
2018-07 19
2018-06 20

Count of people by hour

I need some help working out how many people were on site for each hour.
The data looks like this
Id Roomid, NumPeople, Starttime, Closetime.
1 1 4 2018/10/03 09:06 2018/10/03 12:43
2 2 8 2018/10/03 10:16 2018/10/03 13:12
3 1 6 2018/10/03 13:02 2018/10/03 15:01
What I need out is the max count of people during the hour, each hour
Time | PeoplePresent
9 4
10 12
11 12
12 12
13 14
14 6
15 6
Getting the count of people as the arrived is simple enough, but I can’t think where to start to get the presence for each hour. Can anyone suggest a strategy for this. I ok with the simple SQL stuff but I’m certain this requires some advanced SQL functions.
Tested the following in SQL Server 2008 R2:
You can use a recursive CTE to build the list of hours, including the row id and NumPeople values. Then you can sum them together to get your final output. I put together the following test data based on the question.
CREATE TABLE #times
(
Id int
, Roomid INT
, NumPeople INT
, Starttime DATETIME
, Closetime DATETIME
)
INSERT INTO #times
(
Id
,Roomid
,NumPeople
,Starttime
,Closetime
)
VALUES
(1, 1, 4 , '2018/10/03 09:06', '2018/10/03 12:43')
,(2, 2, 8, '2018/10/03 10:16', '2018/10/03 13:12')
,(3, 1, 6, '2018/10/03 13:02', '2018/10/03 15:01')
;WITH recursive_CTE (id, startHour, currentHour, diff, NumPeople) AS
(
SELECT
Id
,startHour = DATEPART(HOUR, t.Starttime)
,currentHour = DATEPART(HOUR, t.Starttime)
,diff = DATEDIFF(HOUR, Starttime, Closetime)
,t.NumPeople
FROM #times t
UNION ALL
SELECT
r.id
,r.startHour
,r.currentHour + 1
,r.diff
,r.NumPeople
FROM recursive_CTE r
WHERE r.currentHour < startHour + diff
)
SELECT
Time = currentHour
,PeoplePresent = SUM(NumPeople)
FROM recursive_CTE
GROUP BY currentHour
DROP TABLE #times
Query results:
Time PeoplePresent
9 4
10 12
11 12
12 12
13 14
14 6
15 6

Sort dates order between dates

I have two dates as a parameters and list of current dates and same periods of previous years . I need partition list between parameters. Logic is if date between '20171201' AND '20180301' then 1, if date between '20161201' and '20170301' then 2 and so on. But count of periods in list not static, like:
DECLARE #DateEnd DATE = '20180331'
, #DateBeg DATE = '20171201'
DECLARE #tab TABLE([date] DATE)
INSERT INTO #tab ([date])
VALUES('2014-12-01')
, ('2015-01-01')
, ('2015-02-01')
, ('2015-03-01')
, ('2015-12-01')
, ('2016-01-01')
, ('2016-02-01')
, ('2016-03-01')
, ('2016-12-01')
, ('2017-01-01')
, ('2017-02-01')
, ('2017-03-01')
, ('2017-12-01')
, ('2018-01-01')
, ('2018-02-01')
, ('2018-03-01')
Result should be
Date Cnt
2014-12-01 4
2015-01-01 4
2015-02-01 4
2015-03-01 4
2015-12-01 3
2016-01-01 3
2016-02-01 3
2016-03-01 3
2016-12-01 2
2017-01-01 2
2017-02-01 2
2017-03-01 2
2017-12-01 1
2018-01-01 1
2018-02-01 1
2018-03-01 1
use CASE WHEN satetement to check for the date and return the value accordingly
select *,
Cnt = CASE
WHEN date BETWEEN '20171201' AND '20180331' THEN 1
WHEN date BETWEEN '20161201' AND '20170331' THEN 2
WHEN date BETWEEN '20151201' AND '20160331' THEN 3
WHEN date BETWEEN '20141201' AND '20150331' THEN 4
END
from #tab
EDIT :
Or maybe this is what you want ?
this will gives you the begining of the financial year
dateadd(month, - month(date) % 12, date)
your Cnt is no of years between the financial year and today ?
select *,
Cnt = datediff(year, dateadd(month, - month(date) % 12, date), getdate())
from #tab
Using dateadd() within a case expression should enable this:
select
datecol
, case when datecol between #DateBeg and #DateEnd then 1
when datecol between dateadd(year,-1,#DateBeg) and dateadd(year,-1,#DateEnd) then 2
when datecol between dateadd(year,-2,#DateBeg) and dateadd(year,-2,#DateEnd) then 3
when datecol between dateadd(year,-3,#DateBeg) and dateadd(year,-3,#DateEnd) then 4
end
from #tab
also see: http://rextester.com/BTF82190

Select Criteria based on previous 5 days

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