Reputation: 6171
I know the year and the quarter (e.g. "2010" and "4") for a schedule-related milestone and I want to select/create a datetime from it. There are a number of nifty ways to identify the quarter with formats ("qq") of a particular date, but not to go the other way around (or are there?). This is with t-sql / SQL Server.
Note: the datetime should be for the last day of that quarter.
UPDATE: Here is the solution that I ended up using courtesy of gbn, with AaronLS's variable names and then shortened-and-sweetened with Frank Kalis' suggestion :-) It was important to test for all 4 quarters to make sure the year is handled properly. Thanks to everyone who answered!
DECLARE @TheQuarter INT
DECLARE @theYear INT
-- Note: qq = q = quarter for the datepart
SET @TheQuarter = 1
SET @TheYear = 2011
SELECT DATEADD(YEAR, @TheYear-1900, DATEADD(qq, @TheQuarter, -1))
-- 2011-03-31 00:00:00.000
SET @TheQuarter = 2
SET @TheYear = 2011
SELECT DATEADD(YEAR, @TheYear-1900, DATEADD(qq, @TheQuarter, -1))
-- 2011-06-30 00:00:00.000
SET @TheQuarter = 3
SET @TheYear = 2011
SELECT DATEADD(YEAR, @TheYear-1900, DATEADD(qq, @TheQuarter, -1))
-- 2011-09-30 00:00:00.000
SET @TheQuarter = 4
SET @TheYear = 2011
SELECT DATEADD(YEAR, @TheYear-1900, DATEADD(qq, @TheQuarter, -1))
-- 2011-12-31 00:00:00.000
Here are a few q's that fetch the quarter from the date but not the other way around: Calculate the Last Day in the CURRENT quarter; Calculate the last day of the quarter; Best way to store quarter and year in SQL Server?
Upvotes: 6
Views: 9595
Reputation: 38364
This basically gets the first day of the following quarter, and then subtracts one so that you have the last day of the quarter you wanted. (@theQuarter + 1)
adds one to the quarter, then *3 -2
gets the first month of that quarter, and % 12
is required when for the fourth quarter because you add one to 4 to get 5, which gives you 13 but you really want 1, so the % takes care of that.
Finally after casting it all to a date time, we have the first day of the following quarter, thus subtract - 1
at the end to subtract one day and get the last day of the quarter we initially put in.
declare @theQuarter as int;
set @theQuarter = 4;
declare @theYear as int;
set @theYear = 2009;
select
cast(
cast(
( (@theQuarter + 1) * 3 - 2) % 12
as varchar(2))
+ '-01-'
+ cast( (@theYear + (((@theQuarter + 1) * 3 - 2)/ 12) ) as varchar(4))
as datetime) - 1 ;
Upvotes: 1
Reputation: 1352
Looks like you've already found your solution, but just for the sake of it... If you choose a different base date, you can shorten the whole thing to
SELECT DATEADD(YEAR, @TheYear-1900, DATEADD(qq, @TheQuarter, -1))
Since 0 indicates SQL Server's base date of 01.01.1900 (and the first day of a month), using -1 as base date starts off 1 day earlier and then you already have your last day of a month (and end of a quarter). Then you just need to do the rest of the datetime magic and voilà.
Upvotes: 4
Reputation: 56779
Just choose the date from the quarter:
select
case @theQuarter
when 1 then '3/31/' + cast(@theYear as varchar(4))
when 2 then '6/30/' + cast(@theYear as varchar(4))
when 3 then '9/30/' + cast(@theYear as varchar(4))
when 4 then '12/31/' + cast(@theYear as varchar(4))
end as quarterDate
Edit: Adjusted to be last day of quarter instead of first day.
Upvotes: 2
Reputation: 432431
Never use strings for datetime conversions: too much to go wrong with formats, language etc.
Keep it in the datetime type...
Select dateadd(day, -1,
dateadd(year, @year-1900,
dateadd(quarter, @qq, 0)
)
)
Upvotes: 9