Thanks for all for reading my questions, I have fallen a big problem to retrieve date from SQL Server 2012 by providing year, week number and day name.
Suppose I have
Year = 2016
Week number = 1
Day Name ='FRI'
First day of week='SUN'
Expected result:
01-01-2016
How can I do that?
EDIT: I have found similar solution from here but I have no month name.
My suggestion is based on the solution to the question in the link you provided.
Basically, I've created a calendar that holds the dates since January 1st of the year till #x weeks after that, and then queried that calendar:
-- provided data:
DECLARE #Year int = 2016,
#WeekNumber int = 1,
#DayName char(3) = 'Fri';
-- Calculate start date and end date
DECLARE #StartDate date,
#EndDate date;
SELECT #StartDate = CAST('01-01-'+ CAST(#Year as char(4)) as date),
#EndDate = DATEADD(WEEK, #WeekNumber, #StartDate)
-- Create the calendar
;WITH CTE AS
(
SELECT #StartDate as TheDate
UNION ALL
SELECT DATEADD(DAY, 1, TheDate)
FROM CTE
WHERE DATEADD(DAY, 1, TheDate) <= #EndDate
)
-- Finally, query the calendar:
SELECT TheDate
FROM CTE
WHERE DATEPART(WEEK, TheDate) = #WeekNumber
AND YEAR(TheDate) = #Year
AND DATENAME(WEEKDAY, TheDate) LIKE #DayName + '%'
OPTION(MAXRECURSION 0)
results:
TheDate
----------
2016-01-01
Note: This solution will return no rows if the day you specify is mon, since the first week of 2016 starts on Friday.
TRY THIS
DECLARE #Year varchar(4)
DECLARE #WeekDayday varchar(10)
DECLARE #WeekNumber int
SET #Year ='2016'
SET #WeekDayday ='fri'
SET #WeekNumber =1
--used to solve
DECLARE #StartDate datetime
,#EndDate datetime
,#FirstWeek int
SET #StartDate='01-01-'+' '+#Year
SET #EndDate=#StartDate+38
SET #FirstWeek=DATENAME(week,#StartDate)-1
;with AllDates AS
(
SELECT #StartDate AS DateOf, DATENAME(week,#StartDate)-#FirstWeek AS WeekOf, DATENAME(weekday,#StartDate) AS WeekDayOf
UNION ALL
SELECT DateOf+1, DATENAME(week,DateOf+1)-#FirstWeek AS WeekOf, DATENAME(weekday,DateOf+1) AS WeekDayOf
FROM AllDates
WHERE DateOf<#EndDate
)
SELECT
DateOf
FROM AllDates
WHERE WeekOf=#WeekNumber AND WeekDayOf LIKE #WeekDayday+'%'
ORDER BY DateOf
How about improve that answer by evaluate month name by week number:
--given info
DECLARE #Year varchar(4);
DECLARE #MonthName varchar(10);
DECLARE #WeekDayday varchar(10);
DECLARE #WeekNumber int;
SET #Year = '2016';
SET #WeekDayday = 'Tue';
set #WeekNumber = 46;
-- get month number by week
declare #w int = 0;
declare #m int = 1;
while (#w <= #WeekNumber and #m < 13) begin
set #w = datepart(wk, datefromparts(#year, #m, 1));
if (#w <= #WeekNumber and #m < 13) begin
set #m = #m + 1;
end;
end;
set #m = #m -1;
-- get month name
set #MonthName = left(DateName(month ,DateAdd(month ,#m ,0 ) - 1), 3);
--used to solve
DECLARE #StartDate datetime
,#EndDate datetime
,#FirstWeek int
SET #StartDate='01 '+#MonthName+' '+#Year
SET #EndDate=#StartDate+38
SET #FirstWeek=DATENAME(week,#StartDate)-1
;with AllDates AS
(
SELECT #StartDate AS DateOf, DATENAME(week,#StartDate)-#FirstWeek AS WeekOf, DATENAME(weekday,#StartDate) AS WeekDayOf
UNION ALL
SELECT DateOf+1, DATENAME(week,DateOf+1)-#FirstWeek AS WeekOf, DATENAME(weekday,DateOf+1) AS WeekDayOf
FROM AllDates
WHERE DateOf<#EndDate
)
SELECT
DateOf ,WeekOf ,WeekDayOf
FROM AllDates
WHERE datepart(wk, DateOf) = #WeekNumber AND WeekDayOf LIKE #WeekDayday+'%'
ORDER BY DateOf
Related
for example:
--fromdate todate
--2020/10/1 2020/11/01
Output should be like:
--Days dayname
------- ---------------
--2020/10/1 Monday
.. ..
You can use DATENAME to get the WEEKDAY and filter by it:
DATENAME ( WEEKDAY , my_date )
Something like this (the code for generating days is from here)
declare #dt datetime, #dtEnd datetime
set #dt = '2020/10/1'
set #dtEnd = '2020/11/01'
select dateadd(day, number, #dt)
,DATENAME ( WEEKDAY , dateadd(day, number, #dt) )
from
(select number from master.dbo.spt_values
where [type] = 'P'
) n
where dateadd(day, number, #dt) < #dtEnd
AND DATENAME ( WEEKDAY , dateadd(day, number, #dt) ) NOT IN ('Saturday', 'Sunday')
I think this query works well.
declare #result table
(
Days varchar(10),
DayName varchar(20)
)
declare #fromDate date = '2020/10/01'
declare #toDate date = '2020/11/01'
while #fromDate <= #toDate
begin
if DATENAME(weekday, #fromDate) not in ('Saturday', 'Sunday')
begin
insert into #result(Days, DayName)
values(#fromDate, DATENAME(weekday, #fromDate))
end
set #fromDate = DATEADD(day, 1, #fromDate)
end
select *
from #result
I am trying to generate a stock position report as at each month. within my query i have a date variable set at a specific month:
declare #date datetime = CONVERT(DATETIME, '2019-08-13 00:00:00', 121)
declare #lastmonth datetime = (select cast(dateadd(day, -day(getdate()), getdate()) as date))
declare #m int = 0
--**my aim is to ensure that #date = #lastmonth**
while #date<= #lastmonth
Begin
set #m = #m + 1
while #m < 12
Begin
set #date = (select dateadd(mm, #m, #date))
End
End
select
How can I list all dates between two date parameters in SQL Server, without creating a stored procedure, calendar table or recursive function?
There's always the recursive CTE option:
DECLARE #STARTDATE DATETIME
DECLARE #ENDDATE DATETIME
SET #STARTDATE = '2015-01-01'
SET #ENDDATE = '2015-12-31'
;WITH DATE_RANGE (DATES) AS (
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, #STARTDATE), 0)
UNION ALL SELECT DATEADD(DAY, 1, DATES)
FROM DATE_RANGE
WHERE DATEADD(DAY, 1, DATES) <= #ENDDATE)
SELECT DATES
FROM DATE_RANGE
OPTION (MAXRECURSION 0)
Be sure to use the MAXRECURSION option, or your results will be limited to 100 as default.
This uses Row_Number on the spt_values table in Master database to create a list of years, months and dates within the date range.
This is then built into a datetime field, and filtered to only return dates within the date parameters entered.
Very quick to execute and returns 500 years worth of dates (182987 days) in less than 1 second.
Declare #DateFrom datetime = '2000-01-01'
declare #DateTo datetime = '2500-12-31'
Select
*
From
(Select
CAST(CAST(years.Year AS varchar) + '-' + CAST(Months.Month AS varchar) + '-' + CAST(Days.Day AS varchar) AS DATETIME) as Date
From
(select row_number() over(order by number) as Year from master.dbo.spt_values) as Years
join (select row_number() over(order by number) as Month from master.dbo.spt_values) as Months on 1 = 1
join (select row_number() over(order by number) as Day from master.dbo.spt_values) as Days on 1 = 1
Where
Years.Year between datepart(year,#DateFrom) and datepart(year,#DateTo)
and Months.Month between 1 and 12
and
Days.Day between 1 and datepart(day,dateadd(day,-1,dateadd(month,1,(CAST(CAST(Years.Year AS varchar)+'-' + CAST(Months.Month AS varchar) + '-01' AS DATETIME)))))
) as Dates
Where Dates.Date between #DateFrom and #DateTo
order by 1
Following will be a solution for YOU
DECLARE #DATE1 DATE
DECLARE #DATE2 DATE
SET #DATE1 ='20020101'
SET #DATE2 = '20020311'
SELECT #DATE1 as t
into #FromDate
DECLARE cur CURSOR FOR
SELECT t FROM #FromDate
OPEN cur
FETCH NEXT FROM cur INTO #DATE1
WHILE(##FETCH_STATUS=0)
BEGIN
IF(#DATE1<=#DATE2)
INSERT INTO #FromDate
VALUES(DATEADD(DAY,1,#DATE1))
FETCH NEXT FROM cur INTO #DATE1
END
CLOSE cur
DEALLOCATE cur;
SELECT t FROM #FromDate;
DROP TABLE #FromDate;
Simple result.
DECLARE #DATE1 DATE
DECLARE #DATE2 DATE
SET #DATE1 ='20020101'
SET #DATE2 = '20020311'
WHILE(#DATE1<=#DATE2)
Begin
PRINT #DATE1
set #DATE1 = DATEADD(dd,1,#DATE1)
END
I need to display dates of all Mondays in the given date range.
For example, if my start date is 01/05/2015 and end date is 31/05/2015, I need to show
04/05/2015
11/05/2015
18/05/2015
25/05/2015
How is it possible?
This procedure is independent from regions and languages.
Please note the first line with SET DATEFIRST 1.
SET DATEFIRST 1; -- First day of the week is set to monday
DECLARE #DateFrom DateTime ='20150601', #DateTo DateTime = '20150630' ;
WITH CTE(dt)
AS
(
SELECT #DateFrom
UNION ALL
SELECT DATEADD(d, 1, dt) FROM CTE
WHERE dt < #DateTo
)
SELECT dt FROM CTE where datepart ("dw", dt) = 1;
Using a CTE it is possible this way..
DECLARE #DateFrom DateTime ='2015-05-01',
#DateTo DateTime = '2015-05-31'
;WITH CTE(dt)
AS
(
SELECT #DateFrom
UNION ALL
SELECT DATEADD(d, 1, dt) FROM CTE
WHERE dt < #DateTo
)
SELECT 'Monday', dt FROM CTE
WHERE DATENAME(dw, dt) In ('Monday')
Refer: Select dates of a day between two dates.
SELECT [Day],[Dt] FROM dbo.fnGetDatesforAday('7/1/2008','8/31/2008','Sunday')
CREATE FUNCTION fnGetDatesforAday
(
-- Add the parameters for the function here
#DtFrom DATETIME,
#DtTo DATETIME,
#DayName VARCHAR(12)
)
RETURNS #DateList TABLE ([Day] varchar(20),Dt datetime)
AS
BEGIN
IF NOT (#DayName = 'Monday' OR #DayName = 'Sunday' OR #DayName = 'Tuesday' OR #DayName = 'Wednesday' OR #DayName = 'Thursday' OR #DayName = 'Friday' OR #DayName = 'Saturday')
BEGIN
--Error Insert the error message and return
INSERT INTO #DateList
SELECT 'Invalid Day',NULL AS DAT
RETURN
END
DECLARE #TotDays INT
DECLARE #CNT INT
SET #TotDays = DATEDIFF(DD,#DTFROM,#DTTO)-- [NO OF DAYS between two dates]
SET #CNT = 0
WHILE #TotDays >= #CNT -- repeat for all days
BEGIN
-- Pick each single day and check for the day needed
IF DATENAME(DW, (#DTTO - #CNT)) = #DAYNAME
BEGIN
INSERT INTO #DateList
SELECT #DAYNAME,(#DTTO - #CNT) AS DAT
END
SET #CNT = #CNT + 1
END
RETURN
END
SET DATEFIRST 7; -- Set's sunday as first day of week, won't work otherwise
DECLARE #StartDate DATE = '06/01/2015'
DECLARE #EndDate DATETIME = '06/30/2015'
DECLARE #TableOfDates TABLE(DateValue DATETIME)
DECLARE #CurrentDate DATETIME
SET #CurrentDate = #startDate
WHILE #CurrentDate <= #endDate
BEGIN
INSERT INTO #TableOfDates(DateValue) VALUES (#CurrentDate)
SET #CurrentDate = DATEADD(DAY, 1, #CurrentDate)
END
SELECT * FROM #TableOfDates WHERE DATEPART(weekday,Datevalue) = 2
Is it possible to add all the dates between 1st Jan-31-Dec in MS Sql server using query?
If someone has done it before please guide me to right track.
Thanks
DECLARE #dt Date
SET #dt = '2015-01-01'
WHILE #dt < '2016-01-01'
BEGIN
SELECT #dt
--INSERT .....
SET #dt = DATEADD(DAY, 1, #dt)
END
Of course it depends on your table structure
using loop we can achieve this
Declare #date table(d datetime)
Declare #d datetime, #d1 datetime, #d2 datetime
Declare #inc INT
set #d1='20150101'
set #d2='20151231'
Set #inc = DATEDIFF(D, #d1, #d2)
Set #d = #d1
While #d<=#d2
Begin
Insert into #date values (#d)
set #d=#d+1
End
Select d as DateCol from #date
This should do the trick:
DECLARE #year int = 2015
;WITH N(N)AS
(SELECT 1 FROM(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))M(N)),
tally(N)AS(SELECT ROW_NUMBER()OVER(ORDER BY N.N)-1 FROM N,N a,N b,N c,N d,N e,N f)
SELECT top (datediff(d, cast(#year as char(4)), cast(#year + 1 as char(4))))
CAST(DATEADD(d, N, cast(#year as char(4))) as date)
FROM tally
Result:
2015-01-01
2015-01-02
..
..
2015-12-31