我正在学习SQL,我有这个看起来很糟糕的查询来选择过去4个财政/财政季度以及它们之前的几个季度。
如果日期是2018年3月28日,则返回的表格如下:
╔═══╦════════════╦═════════════╗
║ ║ ID ║ QuartersAgo ║
╠═══╬════════════╬═════════════╣
║ 1 ║ 20182 ║ 1 ║
║ 2 ║ 20181 ║ 2 ║
║ 3 ║ 20174 ║ 3 ║
║ 4 ║ 20173 ║ 4 ║
╚═══╩════════════╩═════════════╝
我的查询如下。当然有一个更好,更有效的方式......我喜欢这个是它的工作原理,我可以将它提交到版本控制(不像Excel和PowerBI,我通常会建立这个东西)。
在第一阶段,我根据日历年的月份确定财政年度。
以类似的方式,我将这些年份分解为Quarters以确定当前的财务季度。
一旦我发现我正在设置和确定第n季度前的值。
我不喜欢的是我觉得我应该只是将值插入变量表中,因为我正在确定我是哪个季度。相反,我指定一个值,然后稍后插入。
DECLARE @Today DATE = GETDATE();
DECLARE @ThisCalendarYear VARCHAR(4)
DECLARE @ThisFinancialYear VARCHAR(4)
DECLARE @ThisCalendarMonth INT
DECLARE @Last4FinancialQuarters TABLE(
ID VARCHAR(5) NOT NULL,
QuartersAgo INT NOT NULL
);
DECLARE @LastFinancialQuarter VARCHAR(5)
DECLARE @SecondLastFinancialQuarter VARCHAR(5)
DECLARE @ThirdLastFinancialQuarter VARCHAR(5)
DECLARE @FourthLastFinancialQuarter VARCHAR(5)
SET @ThisCalendarYear = DatePart(Year, @Today)
SET @ThisCalendarMonth = DatePart(Month, @Today)
IF DatePart(Month, @Today) <= 6
SET @ThisFinancialYear = DatePart(Year, @Today)
ELSE
SET @ThisFinancialYear = DatePart(Year, @Today) +1
SET @LastFinancialQuarter = CASE
WHEN @ThisCalendarMonth <= 3 THEN CONCAT(@ThisCalendarYear ,4 - 2)
WHEN @ThisCalendarMonth <= 6 THEN CONCAT(@ThisCalendarYear ,4 - 1)
WHEN @ThisCalendarMonth <= 9 THEN CONCAT(@ThisCalendarYear ,4 - 0)
WHEN @ThisCalendarMonth <= 12 THEN CONCAT(@ThisCalendarYear + 1,4 - 3)
END
SET @SecondLastFinancialQuarter = CASE
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 4 THEN CONCAT(@ThisFinancialYear,3)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 3 THEN CONCAT(@ThisFinancialYear,2)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 2 THEN CONCAT(@ThisFinancialYear,1)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 4 THEN CONCAT(@ThisFinancialYear - 1,4)
END
SET @ThirdLastFinancialQuarter = CASE
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 4 THEN CONCAT(@ThisFinancialYear,2)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 3 THEN CONCAT(@ThisFinancialYear,1)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 2 THEN CONCAT(@ThisFinancialYear - 1,4)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 4 THEN CONCAT(@ThisFinancialYear - 1,3)
END
SET @FourthLastFinancialQuarter = CASE
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 4 THEN CONCAT(@ThisFinancialYear,1)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 3 THEN CONCAT(@ThisFinancialYear - 1,4)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 2 THEN CONCAT(@ThisFinancialYear - 1,3)
WHEN SUBSTRING(@LastFinancialQuarter, 5,1) = 4 THEN CONCAT(@ThisFinancialYear - 1,2)
END
INSERT INTO @Last4FinancialQuarters (ID, QuartersAgo)
VALUES
(@LastFinancialQuarter, 1),
(@SecondLastFinancialQuarter, 2),
(@ThirdLastFinancialQuarter, 3),
(@FourthLastFinancialQuarter, 4);
SELECT * FROM @Last4FinancialQuarters
会感激一些反馈:)谢谢
答案 0 :(得分:3)
拯救的递归CTE:
;WITH cte AS
(
SELECT 1 as QuartersAgo, GETDATE() as DT,
CAST(YEAR(DATEADD(MONTH, 3, GETDATE())) AS VARCHAR(4)) + CAST(DATEPART(QUARTER, DATEADD(MONTH, 3, GETDATE())) AS VARCHAR(1)) as FinancialQuarter
UNION ALL
SELECT QuartersAgo + 1, DATEADD(MONTH, -3, cte.DT),
CAST(YEAR(DATEADD(MONTH, 3, DATEADD(MONTH, -3, cte.DT))) AS VARCHAR(4)) + CAST(DATEPART(QUARTER, DATEADD(MONTH, 3, DATEADD(MONTH, -3, cte.DT))) AS VARCHAR(1))
FROM cte
WHERE QuartersAgo < 4
)
SELECT FinancialQuarter, QuartersAgo FROM cte
这是输出:
FinancialQuarter QuartersAgo
20182 1
20181 2
20174 3
20173 4
以下是一些要点:
要获得今天作为澳大利亚财政季度的日期,请加上3个月并将该年度结束到该季度(您可以通过DATEPART(季度(日期))获得,所以,像这样:< / p>
CAST(年(DATEADD(月,3,GETDATE()))AS VARCHAR(4))+ CAST(DATEPART(QUATTER,DATEADD(月,3,GETDATE()))AS VARCHAR(1))
答案 1 :(得分:0)
我还使用Recursive CTE
来解决此问题(我确实从@Max解决方案中获取了帮助) -
declare @Today date = getdate()
declare @CalendarMonth int = datepart(month, @Today)
declare @LastFinancialQuarterDate date = dateadd(month, (case when @CalendarMonth <= 6 then 6 else 18 end) - @CalendarMonth, @Today)
;with cte as
(
select cast(datepart(year, @LastFinancialQuarterDate) as varchar(4))
+
cast(datepart(quarter, @LastFinancialQuarterDate) as varchar(1)) as ID,
1 as QuartersAgo
union all
select cast(datepart(year, dateadd(month, cte.QuartersAgo * -3, @LastFinancialQuarterDate)) as varchar(4))
+
cast(datepart(quarter, dateadd(month, cte.QuartersAgo * -3, @LastFinancialQuarterDate)) as varchar(1)) as ID,
(cte.QuartersAgo + 1) as QuartersAgo
from cte
where cte.QuartersAgo < 4
)
select * from cte
我做的第一件事就是找到属于上一个澳大利亚季度的日期并将其设置为@LastFinancialQuarterDate
变量。之后我在Recursive CTE
中使用该变量来遍历过去的四个季度。