I have a requirement of extracting data of given quarter.
For example if I pass
declare #year int=2021
declare #q int=2
the function should return
year quarterfrom quarterto
--------------------------------
2021 2021-04-01 2021-06-30
-----------------------------------
How can we achieve that in MSSQL (2012)
Some fairly trivial date maths works:
DECLARE #year int = 2021,
#q int = 2;
SELECT #Year AS Year,
DATEADD(MONTH, 3 * (#q-1),DATEFROMPARTS(#year,1,1)),
EOMONTH(DATEADD(MONTH, (3 * (#q-1))+2,DATEFROMPARTS(#year,1,1)));
This, of course, assumes that the quarters start on the 1st, 4th, 7th and 10th months.
Related
I have a query that converts week and year to date.
But it returns the exact date.
But what i want is, I need the date to be such a day, that is same as the first day of the year.
dateadd (week, PromisedWeek-1, dateadd (year, PromisedYear-1900, 0)) - 4 -
datepart(dw, dateadd (week, PromisedWeek-1, dateadd (year, PromisedYear-1900, 0)) - 4) + 1
Hypothetical example.
My current query does is:
If week is 4 and year 2017, returns 26-Sun-2017
My need:
If week is 4 and year 2017 and January 1st was a Wednesday, its should return 29-Wednesday-2017.
Hoping that you guys get what I am trying to explain.
I need the query to return such a date which has the same day as that of the current year's 1st day.
Unless I'm reading this wrong, you're making things too hard on yourself. Just do this:
declare #year int; set #year = 2017;
declare #week int; set #week = 4;
select dateadd(week, #week, dateadd(year, #year - 1900, 0))
Result:
2017-01-29 00:00:00.000
The inner dateadd() gives you the first day of the requested year (Jan 1), regardless of weekday. If it's a Wednesday, you'll get a Wednesday. This year, it's Sunday. The outer dateadd() then adds full weeks to that, so you end up with the same day of the week, just like you asked.
If that's not what you want, please explain how it needs to be more complicated.
This is pretty easy if you have a calendar table. A calendar table is a table that contains every date and its parts for a given range. I created mine for 2010 to 2020 with this code:
declare #start_dt as date = '1/1/2010';
declare #end_dt as date = '1/1/2020';
declare #dates as table (
date_id date primary key,
date_year smallint,
date_month tinyint,
date_day tinyint,
weekday_id tinyint,
weekday_nm varchar(10),
month_nm varchar(10),
day_of_year smallint,
quarter_id tinyint,
first_day_of_month date,
last_day_of_month date,
start_dts datetime,
end_dts datetime
)
while #start_dt < #end_dt
begin
insert into #dates(
date_id, date_year, date_month, date_day,
weekday_id, weekday_nm, month_nm, day_of_year, quarter_id,
first_day_of_month, last_day_of_month,
start_dts, end_dts
)
values(
#start_dt, year(#start_dt), month(#start_dt), day(#start_dt),
datepart(weekday, #start_dt), datename(weekday, #start_dt), datename(month, #start_dt), datepart(dayofyear, #start_dt), datepart(quarter, #start_dt),
dateadd(day,-(day(#start_dt)-1),#start_dt), dateadd(day,-(day(dateadd(month,1,#start_dt))),dateadd(month,1,#start_dt)),
cast(#start_dt as datetime), dateadd(second,-1,cast(dateadd(day, 1, #start_dt) as datetime))
)
set #start_dt = dateadd(day, 1, #start_dt)
end
select *
into Calendar
from #dates
Once you have a calendar table you can query for the correct weekday in the PromisedWeek
declare #PromisedYear as numeric
declare #PromisedWeek as int
set #PromisedYear = 2017
set #PromisedWeek = 4
select concat(date_day, '-', weekday_nm, '-', #PromisedYear)
from Calendar as c
where
weekday_id =
(select weekday_ID
from Calendar
where date_year = #PromisedYear
and day_of_year = 1
)
and datepart(week, date_id) = #PromisedWeek
and date_year = #PromisedYear
Turns out that January 1st 2017 was a Sunday and the 4th Sunday in 2017 was January 22nd, so the return is 22-Sunday-2017
I have a query for calculating first and last date in the week, according to given date. It is enough to set #dDate and the query will calculate first (monday) and last date (sunday) for that week.
Problem is, that is calculating wrong and I don't understand why.
Example:
#dDate = 2019-10-03 (year-month-day).
Result:
W_START W_END
2019-09-25 2019-10-01
But it should be:
2019-09-30 2019-10-06
Why is that?
Query:
set datefirst 1
declare #dDate date = cast('2019-10-16' as date)
select #dDAte
declare #year int = (select DATEPART(year, #dDAte))
select #year
declare #StartingDate date = cast(('' + cast(#year as nvarchar(4)) + '-01-01') as date)
select #StartingDate
declare #dateWeekEnd date = (select DATEADD(week, (datepart(week, cast(#dDate as date)) - 1), #StartingDate))
declare #dateWeekStart date = dateadd(day, -6, #dateWeekEnd)
select #dateWeekStart W_START, #dateWeekEnd W_END
Days of the week are so complicated. I find it easier to remember that 2001-01-01 fell on a Monday.
Then, the following date arithmetic does what you want:
select dateadd(day,
7 * (datediff(day, '2001-01-01', #dDate) / 7),
'2001-01-01' -- 2001-01-01 fell on a Monday
)
I admit this is something of a cop-out/hack. But SQL Server -- and other databases -- make such date arithmetic so cumbersome that simple tricks like this are handy to keep in mind.
I need to pass one DateTime and DayOfWeek and from that I need to get DateTime of that selected week.
--Sunday-1
--Monday-2
--Tuesday-3
--Wednesday-4
--Thursday-5
--Friday-6
--Saturday-7
DECLARE #DayOfWeek TINYINT = 1
DECLARE #Date DATETIME = '2016-07-21 23:47:11.133'
SELECT DATEADD(wk, DATEDIFF(wk,0,#Date), #DayOfWeek)
for eg:
for this, I need to get date like 2016-07-24 00:00:00 which is Sunday on that week.
Any Ideas?
With datetime values you must be very carefull! Especially the index of a day is tricky. You should always think of culture specific differences:
--The first of January was a Friday in 2016
DECLARE #testDate DATE = {d'2016-01-01'};
--I try this with German culture, this starts with Monday
SET LANGUAGE GERMAN;
SELECT ##DATEFIRST,DATEPART(WEEKDAY,#testDate); --in Germany the Friday was 5th day
--Now the same with English culture, starting on Sunday
SET LANGUAGE ENGLISH;
SELECT ##DATEFIRST,DATEPART(WEEKDAY,#testDate); --in English culture this is the 6th day
--You can get this culture independant by adding those values with Modulo 7
SET LANGUAGE GERMAN;
SELECT (##DATEFIRST + DATEPART(WEEKDAY,#testDate)) % 7; --in Germany the Friday was 5th day
SET LANGUAGE ENGLISH;
SELECT (##DATEFIRST + DATEPART(WEEKDAY,#testDate)) % 7; --in English culture this is the 6th day
Now both queries return the same value for Friday, the 6.
Your example shows the Sunday as first day of the week, so the Sunday of the week to the given day should be the 17th of July actually. Your expected output (24th of July) is the first day of the following week, isn't it?
Try this:
DECLARE #DayOfWeek TINYINT = 1;
DECLARE #Date DATETIME = '2016-07-21 23:47:11.133';
SELECT CAST(#Date + #DayOfWeek - (##DATEFIRST + DATEPART(WEEKDAY,#Date)) % 7 AS DATE)
I have to get/create date from the user input of week of month (week number in that month - 1st,2nd,3rd,4th and last) and day of week (sunday,monday..) in SQL server.
Examples:
4th Sunday of every month, Last Friday of every month, First Monday etc.
I was able to do it easily in .net but SQL server does seem limited in the date functions.
I am having to use lot of logic to get the date. To calculate the date using the above two parameters I had to use lot of datepart function.
Any suggestions on how to come up with the optimal SQL query for such a function?
I created a function other day for another OP GET Month, Quarter based on Work Week number
This function takes the current year as default it can be further modified to take Year as a parameter too.
an extension to that function can produce the results you are looking for ....
WITH X AS
(
SELECT TOP (CASE WHEN YEAR(GETDATE()) % 4 = 0 THEN 366 ELSE 365 END)-- to handle leap year
DATEADD(DAY
,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1
, CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '0101' )
DayNumber
From master..spt_values
),DatesData AS(
SELECT DayNumber [Date]
,DATEPART(WEEKDAY,DayNumber) DayOfTheWeek
,DATEDIFF(WEEK,
DATEADD(WEEK,
DATEDIFF(WEEK, 0, DATEADD(MONTH,
DATEDIFF(MONTH, 0, DayNumber), 0)), 0)
, DayNumber- 1) + 1 WeekOfTheMonth
FROM X )
SELECT * FROM DatesData
WHERE DayOfTheWeek = 6 -- A function would expect these two parameters
AND WeekOfTheMonth = 4 -- #DayOfTheWeek and #WeekOfTheMonth
Here is a general formula:
declare #month as datetime --set to the first day of the month you wish to use
declare #week as int --1st, 2nd, 3rd...
declare #day as int --Day of the week (1=sunday, 2=monday...)
--Second monday in August 2015
set #month = '8/1/2015'
set #week = 2
set #day = 2
select dateadd(
day,
((7+#day) - datepart(weekday, #month)) % 7 + 7 * (#week-1),
#month
)
You can also find the last, 2nd to last... etc with this reverse formula:
--Second to last monday in August 2015
set #month = '8/1/2015'
set #week = 2
set #day = 2
select
dateadd(
day,
-((7+datepart(weekday, dateadd(month,1,#month)-1)-#day)) % 7 - 7 * (#week-1),
dateadd(month,1,#month)-1
)
How do i get the date for last friday of the month in T-SQL?
I will be passing the year and month as parameter,e.g, 201211.
If I pass '201211' as parameter it should return me '20121130' as answer as it's the date of last friday of month of november'12.
The 5 January 1900 was a Friday. This uses that a base date and calculates the last Friday in any given month though you must give it a date during the month rather than just the month itself. Replace the 2012-12-01 in this with a date in your month
SELECT DATEADD(DY,DATEDIFF(DY,'1900-01-05',DATEADD(MM,DATEDIFF(MM,0,'2012-12-01'),30))/7*7,'1900-01-05')
You can also use this to get the last Saturday by replacing the 1900-01-05 WITH 1900-01-06 etc.
This would be much simpler using a calendar table; after creating the appropriate columns for your own needs you can just write this:
select
max([Date])
from
dbo.Calendar
where
YearAndMonth = 201211 and
DayOfWeek = 'Friday'
A calendar table is generally a much better solution for determining dates than using functions because the code is much more readable and you can use your own definition of things like WeekNumber, FinancialQuarter etc. that vary widely between countries and even companies.
I created a scalar function for this:
create function [dbo].[lastDWMonth]
(
#y int
,#m int
,#dw int
)
returns date
as
begin
declare #d date
;with x as
(
select datefromparts(#y,#m,1) d
union all
select dateadd(day,1,d) from x where d < eomonth(datefromparts(#y,#m,1))
)
select
#d = max(d)
from
x
where
datepart(dw,d) = #dw
return #d
end
Declare #d1 datetime = '2019-12-23'
Declare #searchDay int = 2 -- monday
select DATEADD(DAY, #searchDay-DATEPART(WEEKday, DateADD(day,-1, DATEADD(month, DATEDIFF(MONTH, 0, #d1)+1, 0))),DateADD(day,-1, DATEADD(month, DATEDIFF(MONTH, 0, #d1)+1, 0)))
This will give you Date on last Monday of the month, you can change your search by changing value in #searchDay