问题
I'm trying to construct a query that will map two columns, one, a date from a table, the second column an alias to show what quarter and financial year the date falls into.
Unfortunately I don't have enough knowledge of SQL to know where to begin. I know that I'd do this with a combination of getdate()
and dateadd(MONTH,,)
however nothing that I've put together has come close to working.
To further complicate this the financial years in Australia go from 1st July- 30th of June so quarter one of financial year 2012 would start from July 1st 2012.
I can do this without a statement however I'd much rather have it in a statement as it's going to be used in an SSRS report and a C# application and it would make maintenance significantly easier.
回答1:
This should work:-
SELECT
MyDate,
CASE
WHEN MONTH(MyDate) BETWEEN 1 AND 3 THEN convert(char(4), YEAR(MyDate) - 1) + 'Q3'
WHEN MONTH(MyDate) BETWEEN 4 AND 6 THEN convert(char(4), YEAR(MyDate) - 1) + 'Q4'
WHEN MONTH(MyDate) BETWEEN 7 AND 9 THEN convert(char(4), YEAR(MyDate) - 0) + 'Q1'
WHEN MONTH(MyDate) BETWEEN 10 AND 12 THEN convert(char(4), YEAR(MyDate) - 0) + 'Q2'
END AS Quarter
FROM
MyTable
Output:-
MyDate Quarter
---------- --------
2011-01-01 "2010Q3"
2011-04-01 "2010Q4"
2011-07-01 "2011Q1"
2011-10-01 "2011Q2"
回答2:
This method doesn't require a CASE statement, and works for any monthly fiscal calendar.
DECLARE @firstMonthOfFiscalQ1 int = 7; --1=January
SELECT DateColumn
, FLOOR(((12 + MONTH(DateColumn) - @firstMonthOfFiscalQ1) % 12) / 3 ) + 1 AS FiscalQuarter
FROM SomeTable
WHERE 1=1;
回答3:
I think it would be easiest to do this with CASE
SELECT
date
, CASE
WHEN MONTH(date) BETWEEN 7 AND 9 THEN 'First Quarter'
WHEN MONTH(date) BETWEEN 10 AND 12 THEN 'Second Quarter'
WHEN MONTH(date) BETWEEN 1 AND 3 THEN 'Third Quarter'
WHEN MONTH(date) BETWEEN 4 AND 6 THEN 'Fourth Quarter'
END AS quarter
FROM Stuff
回答4:
Just in case you want to do some wacky mathematical operations to avoid a case statement:
select mydate,
convert(char(4), year(mydate) - (((DATEPART(qq, mydate) - ((DATEPART(qq, mydate) + 1) % 4) + 1) / -4) + 1)) +
'Q' + convert(char(1), ((DATEPART(qq, mydate) + 1) % 4) + 1) quar
from sampleData
回答5:
Consider creating an equivalent of a Date Dimension table from a data warehouse. This would have one row per day for every year your data could possibly cover (start from some reasonable epoch and go forward until some reasonably far future date).
Within this table, you would have columns describing info about every day - including calendar year, half-year, quarter, month; and fiscal year, half-year, quarter.
Your report then simply joins to this table based on date to pull this info. This gives you future support for other info about dates also, and removes the responsibility of this calculation from each individual reporting query.
回答6:
I found that using 'Explosion Pills' result worked, but I wanted mine to look like the answer by 'Adam Ralph', however I kept experiencing errors. I was able to work around this and created a new CASE
example:
CASE -- Results: 2011 (Financial Year )
WHEN MONTH(MyDate) BETWEEN 1 AND 3 THEN (YEAR(MyDate) - 1)
WHEN MONTH(MyDate) BETWEEN 4 AND 6 THEN (year(MyDate) - 1)
WHEN MONTH(MyDate) BETWEEN 7 AND 9 THEN (YEAR(MyDate) - 0)
WHEN MONTH(MyDate) BETWEEN 10 AND 12 THEN (YEAR(MyDate) - 0)
END AS FYr,
CASE -- Results: Q4 (Financial Qtr)
WHEN MONTH(MyDate) BETWEEN 7 AND 9 THEN 'Q1'
WHEN MONTH(MyDate) BETWEEN 10 AND 12 THEN 'Q2'
WHEN MONTH(MyDate) BETWEEN 1 AND 3 THEN 'Q3'
WHEN MONTH(MyDate) BETWEEN 4 AND 6 THEN 'Q4'
END AS FQtr,
-- https://stackoverflow.com/a/22170892/2337102
CASE -- Results: 2011-Q4 (Financial Yr-Qtr)
WHEN MONTH(MyDate) BETWEEN 1 AND 3 THEN concat((YEAR(MyDate) - 1), '-', 'Q3')
WHEN MONTH(MyDate) BETWEEN 4 AND 6 THEN concat((YEAR(MyDate) - 1), '-', 'Q4')
WHEN MONTH(MyDate) BETWEEN 7 AND 9 THEN concat((YEAR(MyDate) - 0), '-', 'Q1')
WHEN MONTH(MyDate) BETWEEN 10 AND 12 THEN concat((YEAR(MyDate) - 0), '-', 'Q2')
END AS FYrQtr,
CASE -- Results: 11-Q4 (Financial (short) Yr-Qtr)
WHEN MONTH(MyDate) BETWEEN 1 AND 3 THEN concat((date_format(MyDate, '%y') - 1), '-', 'Q3')
WHEN MONTH(MyDate) BETWEEN 4 AND 6 THEN concat((date_format(MyDate, '%y') - 1), '-', 'Q4')
WHEN MONTH(MyDate) BETWEEN 7 AND 9 THEN concat((date_format(MyDate, '%y') - 0), '-', 'Q1')
WHEN MONTH(MyDate) BETWEEN 10 AND 12 THEN concat((date_format(MyDate, '%y') - 0), '-', 'Q2')
END AS FYrQtr,
CASE -- Results: 2011-2012/Q4 (Financial Range Yr/Qtr)
WHEN MONTH(MyDate) BETWEEN 1 AND 3 THEN concat(YEAR(MyDate) - 1,'-', YEAR(MyDate), '/', 'Q3')
WHEN MONTH(MyDate) BETWEEN 4 AND 6 THEN concat(YEAR(MyDate) - 1,'-', YEAR(MyDate), '/', 'Q4')
WHEN MONTH(MyDate) BETWEEN 7 AND 9 THEN concat(YEAR(MyDate) - 0,'-', YEAR(MyDate) + 1, '/', 'Q1')
WHEN MONTH(MyDate) BETWEEN 10 AND 12 THEN concat(YEAR(MyDate) - 0,'-', YEAR(MyDate) + 1, '/', 'Q2')
END AS FRangeQtr,
CASE -- Results: 11-12/Q4 (Financial Range (short) Yr/Qtr)
WHEN MONTH(MyDate) BETWEEN 1 AND 3 THEN concat((date_format(MyDate, '%y') - 1),'-', (date_format(MyDate, '%y')), '/', 'Q3')
WHEN MONTH(MyDate) BETWEEN 4 AND 6 THEN concat((date_format(MyDate, '%y') - 1),'-', (date_format(MyDate, '%y')), '/', 'Q4')
WHEN MONTH(MyDate) BETWEEN 7 AND 9 THEN concat((date_format(MyDate, '%y') - 0),'-', (date_format(MyDate, '%y') + 1), '/', 'Q1')
WHEN MONTH(MyDate) BETWEEN 10 AND 12 THEN concat((date_format(MyDate, '%y') - 0),'-', (date_format(MyDate, '%y') + 1), '/', 'Q2')
END AS FRangeQtr2,
I am adding my answer hoping it will help someone else who comes via Google and experiences issues.
回答7:
A few years late to the game, but here's my quick-easy-clean method for Australians using GetDate(). Even your accounting calendar is upside-down :)
SELECT CHOOSE(MONTH(GetDate()),'3Q','3Q','3Q','4Q','4Q','4Q','1Q','1Q','1Q','2Q','2Q','2Q') AS AccountingQuarter
The SQL choose command takes the month of the date as the parameter, then chooses from the 12 available options. Of course, most other systems would start with 1Q/Q1 in the first choice.
回答8:
Maybe I don't understand the question but the accepted answer does not seem correct. Financial quarter depends on which month the financial year starts, so it will always (?) be a calculation with 2 dates.
Here's what worked for me, no case statement:
CEILING((DATEDIFF(MONTH, FinYearStartDate, MonthStartDate)) / 3) + 1
回答9:
SELECT
MyDate,
CASE
WHEN MONTH(MyDate) IN (1,2,3) THEN convert(char(4), YEAR(MyDate) - 1) + 'Q3'
WHEN MONTH(MyDate) IN (4,5,6) THEN convert(char(4), YEAR(MyDate) - 1) + 'Q4'
WHEN MONTH(MyDate) IN (7,8,9) THEN convert(char(4), YEAR(MyDate) - 0) + 'Q1'
WHEN MONTH(MyDate) IN (10,11,12) THEN convert(char(4), YEAR(MyDate) - 0) + 'Q2'
END AS Quarter FROM MyTable
The above answers do not consider the final month of the quarter
eg. between 1 and 3 will only return months 1 and 2...
回答10:
SELECT Opendate,Month(Opendate),
(CASE WHEN (Month(Opendate)/6.0)<=1 THEN 1 ELSE 2 END) HALF_YEAR
FROM TableName where Opendate <> '1900-01-01 00:00:00.000'
回答11:
Here's an alternative to the accepted answer:
declare @tbl table (MyDate datetime)
insert into @tbl values ('2011-01-01')
insert into @tbl values ('2011-04-01')
insert into @tbl values ('2011-07-01')
insert into @tbl values ('2011-10-01')
SELECT CAST(MyDate AS DATE) as MyDate, CAST(YEAR(DATEADD(MONTH, -6, MyDate)) AS VARCHAR(4)) + 'Q'
+ CAST(DATEPART(q,DATEADD(MONTH, -6, MyDate)) AS VARCHAR(1)) AS Quarter
FROM @tbl
Output:
MyDate Quarter
---------- -------
2011-01-01 2010Q3
2011-04-01 2010Q4
2011-07-01 2011Q1
2011-10-01 2011Q2
This works even if MyDate is something like August 31 - if you subtract 6 months from 8/31 in SQL, you get 2/28 (although 2/31 doesn't exist, MSSQL still knows you probably want the last day of the month). Since the quarter is based on the month of the year, this approach works.
回答12:
This code converts date to year and month, which is beginning of a quarter.
DATEADD(quarter, DATEDIFF(quarter, 0, @date), 0) year_and_first_month_of_quarter
So the months will be always:
YYYY-01-01
YYYY-04-01
YYYY-07-01
YYYY-10-01
Good thing about it - result is in datetime format.
回答13:
declare @sdate date='2017-12-01'
declare @edate date='2018-07-01'
;with rs as
(
select 1 [QNum],@sdate StDT
union all
select [QNum]+1, DATEADD(qq,1,stdt) from rs where [QNum]<=datediff(qq,@sdate,@edate)
)
select QNum, convert(varchar(10),StDT,105) StDT,convert(varchar(10),dateAdd(m,3,DATEADD(d, -1, DATEADD(qq,DATEDIFF(qq, 0, stdt) + 1, 0))),105)EndDT from rs
--select left(datename(mm,s),3) + ' ' +cast(year(s) as varchar) from rs
回答14:
We already have a sysDate table that contains dates from Jan 1, 1900 to Dec 31, 2030 that we use for processing. We were asked to do fiscal year handling, and so we modified our table to include FiscalYearString varchar(9)
, FiscalYear int
and FiscalQuarter int
columns.
The script we use to update these columns is this:
DECLARE @StartingMonthOfFiscalYear INT = 4 -- 1-Jan, 2-Feb, 3-Mar, 4-Apr, 5-May, 6-Jun, 7-Jul, 8-Aug, 9-Sep, 10-Oct, 11-Nov, 12-Dec
UPDATE sysDate
SET FiscalYear = CASE WHEN MONTH([Date]) < @StartingMonthOfFiscalYear
THEN YEAR([Date])-1
ELSE YEAR([Date]) END,
FiscalYearString = CASE WHEN MONTH([Date]) < @StartingMonthOfFiscalYear
THEN CAST(YEAR([Date])-1 AS Varchar(4))+'/'+CAST(YEAR([Date]) AS Varchar(4))
ELSE CAST(YEAR([Date]) AS Varchar(4))+'/'+CAST(YEAR([Date])+1 AS Varchar(4)) END,
FiscalQuarter = CASE WHEN MONTH([Date]) < @StartingMonthOfFiscalYear
THEN ((MONTH([Date]) + 12 - @StartingMonthOfFiscalYear) / 3) + 1
ELSE ((MONTH([Date]) - @StartingMonthOfFiscalYear) / 3) + 1 END
This updates over 47,000 rows in less than 1 second, saving us from having to recalculate every time we need it.
回答15:
I went looking for an answer today and decided that I should post my solution as it avoids a CASE statement:
select DATEPART(Quarter,dateadd(m,6,YourDate))/* add six months to move to FY */ qq
This is written for the Australian Financial year which is six months adjusted, you can see what I'm doing from this.
回答16:
it may helps someone
declare @dt uddt
select @dt=getdate()
select case when month(@dt) between 1 and 3 then 'Q4'
when month(@dt) between 4 and 6 then 'Q1'
when month(@dt) between 6 and 9 then 'Q2'
when month(@dt) between 9 and 12 then'Q3'
end as [Quarter] ,DATEADD(quarter, DATEDIFF(quarter, 0, @dt), 0)
year_and_first_date_of_quarter,
DATEADD(d, -1, DATEADD(q,DATEDIFF(q, 0, @dt) + 1, 0))
year_and_last_date_of_quarter
来源:https://stackoverflow.com/questions/8738818/showing-what-quarter-of-a-financial-year-a-date-is-in