查找包含会计年度和季度的 sql 日期
Finding sql date with account year and Quarter
我是新来的 sql 我遇到了一个问题
我需要通过将季度作为字符串字符串和年份
传递来创建 return 任何季度的开始和结束日期的存储过程
例如:当我通过 exec spname '2014-15','jul-sep'
时,它应该是七月的开始日期和九月的结束日期
不清楚为什么您不只提供年份和季度作为输入参数。以下程序应 return 季度开始和结束:
alter procedure spQuarter (
@yearStr VARCHAR(7),
@QuarterStr VARCHAR(20)
)
AS
BEGIN
DECLARE @year INT = CAST(SUBSTRING(@yearStr, 1, 4) AS INT)
DECLARE @QuarterId INT = (CASE
WHEN @QuarterStr = 'jan-mar' THEN 4
WHEN @QuarterStr = 'apr-jun' THEN 1
WHEN @QuarterStr = 'jul-sep' THEN 2
WHEN @QuarterStr = 'oct-dec' THEN 3
END)
DECLARE @startOfYStr VARCHAR(20) = CAST (@year AS VARCHAR) + '01' + '01'
PRINT @yearStr
PRINT @startOfYStr
DECLARE @startDate DATE = CAST(@startOfYStr AS DATE)
DECLARE @startOfQ DATE = DATEADD(quarter, @QuarterId, @startDate)
DECLARE @endOfQ DATE = DATEADD(day, -1, DATEADD(quarter, @QuarterId + 1, @startDate))
SELECT @startOfQ, @endOfQ
END
GO
测试:
exec spQuarter '2014-15', 'jan-mar' --> 2015-01-01 2015-03-31
exec spQuarter '2014-15', 'apr-jun' --> 2014-04-01 2014-06-30
exec spQuarter '2014-15', 'oct-dec' --> 2014-10-01 2014-12-31
应该对输入参数执行一些额外的检查,但这应该是您需要的一个好的开始。
评论
首先对您的代码发表一些评论:
没有理由在这些作业中使用 select
。第二种形式是您所需要的,所有额外的噪音和括号嵌套都无济于事。在某些情况下,您确实需要子查询,但不需要简单的表达式。
-- bad
set @StartMonth = (select month('2014-'+substring(ltrim(rtrim(@Qmonth)),1,3)+'-01') as mnth1)
-- better
set @StartMonth = month('2014-' + substring(ltrim(rtrim(@Qmonth)), 1, 3) + '-01')
出于我不确定的原因,您开始混用 select
语法。但请注意,您可以说 select <result> = <expr>
或 select <expr> as <result>
。 as
完全可选,但强烈推荐。
-- error
select from_dt as (select DATEADD(month,@StartMonth-1,DATEADD(year,@ac_year-1900,0)))
-- ok
select DATEADD(month, @StartMonth-1, DATEADD(year, cast(@ac_year-1900 as int), 0)) as from_dt
您尝试用 string/character 值进行减法时出现另一个错误。我想我得到的东西更接近你的想法,但我不保证这行代码是完全正确的。
接下来,您的论点在另一个片段中消失了。我相信您希望在第二个 set
的第 4 个位置有 3 个字符。 Substring()
的第三个参数需要是字符数长度而不是结束位置。所以使用 4, 3
而不是 5, 7
.
-- wrong part of the date
set @Endmonth =(select month('2014-'+substring(ltrim(rtrim(@Qmonth)),5,7)+'-01') as month2)
-- correct part of the date
set @Endmonth = month('2014-' + substring(ltrim(rtrim(@Qmonth)), 4, 3) + '-01')
这些更改应该会让您回到正确的轨道上,尽管您还没有达到必须在本季度末找到该月最后一天的地步。我会继续提供我自己的方法。
工作代码
declare @q int =
set @q = /* ignoring everything after the first three characters */
case lower(substring(@QMonth, 1, 3))
when 'jan' then 0 when 'apr' then 1 when 'jul' then 2 when 'oct' then 3
end;
declare @y int;
set @y = cast(left(@ac_year, 4) as int); /* assuming this contains a value like '2014-15' */
set @StartMonth = dateadd(quarter, @q, dateadd(year, @y - 2000, '2000-01-01');
set @EndMonth = dateadd(day, -1, dateadd(quarter, 1, @StartMonth));
您将需要查看输出参数以获取实际 return 两个日期值的过程。我让你自己处理。
您只需像这样传递年份参数 '2014-2015' 而不是 2014-15 和低于 sp 就可以了
create proc spQuarter
(
@YEAR VARCHAR(10),
@Quarter VARCHAR(10),
)
AS
BEGIN
DECLARE @QuarterId INT = (CASE
WHEN @Quarter = 'jan-mar' THEN 1
WHEN @Quarter = 'apr-jun' THEN 2
WHEN @Quarter = 'jul-sep' THEN 3
WHEN @Quarter = 'oct-dec' THEN 4
END)
DECLARE @PreYear VARCHAR(10) = (SELECT top 1 items from dbo.Split(@year,'-'))
DECLARE @NextYear VARCHAR(10)= (SELECT top 1 items from dbo.Split(@year,'-')
where items not in(SELECT top 1 items from dbo.Split(@year,'-')))
DECLARE @SDate Datetime
SET @SDate = (Case @QuarterId When 1 then CONVERT(Datetime,'01-01-'+ @NextYear )
when 2 then CONVERT(Datetime,'01-04-'+ @PreYear)
when 3 then CONVERT(Datetime,'01-07-'+ @PreYear)
when 4 then CONVERT(Datetime,'01-10-'+ @PreYear) end)
SELECT @SDate as StartDate ,DATEADD (dd, -1, DATEADD(qq, DATEDIFF(qq, 0, @SDate) +@QuarterId ,0)) as EndDate
END
我是新来的 sql 我遇到了一个问题 我需要通过将季度作为字符串字符串和年份
传递来创建 return 任何季度的开始和结束日期的存储过程例如:当我通过 exec spname '2014-15','jul-sep'
时,它应该是七月的开始日期和九月的结束日期
不清楚为什么您不只提供年份和季度作为输入参数。以下程序应 return 季度开始和结束:
alter procedure spQuarter (
@yearStr VARCHAR(7),
@QuarterStr VARCHAR(20)
)
AS
BEGIN
DECLARE @year INT = CAST(SUBSTRING(@yearStr, 1, 4) AS INT)
DECLARE @QuarterId INT = (CASE
WHEN @QuarterStr = 'jan-mar' THEN 4
WHEN @QuarterStr = 'apr-jun' THEN 1
WHEN @QuarterStr = 'jul-sep' THEN 2
WHEN @QuarterStr = 'oct-dec' THEN 3
END)
DECLARE @startOfYStr VARCHAR(20) = CAST (@year AS VARCHAR) + '01' + '01'
PRINT @yearStr
PRINT @startOfYStr
DECLARE @startDate DATE = CAST(@startOfYStr AS DATE)
DECLARE @startOfQ DATE = DATEADD(quarter, @QuarterId, @startDate)
DECLARE @endOfQ DATE = DATEADD(day, -1, DATEADD(quarter, @QuarterId + 1, @startDate))
SELECT @startOfQ, @endOfQ
END
GO
测试:
exec spQuarter '2014-15', 'jan-mar' --> 2015-01-01 2015-03-31
exec spQuarter '2014-15', 'apr-jun' --> 2014-04-01 2014-06-30
exec spQuarter '2014-15', 'oct-dec' --> 2014-10-01 2014-12-31
应该对输入参数执行一些额外的检查,但这应该是您需要的一个好的开始。
评论
首先对您的代码发表一些评论:
没有理由在这些作业中使用 select
。第二种形式是您所需要的,所有额外的噪音和括号嵌套都无济于事。在某些情况下,您确实需要子查询,但不需要简单的表达式。
-- bad
set @StartMonth = (select month('2014-'+substring(ltrim(rtrim(@Qmonth)),1,3)+'-01') as mnth1)
-- better
set @StartMonth = month('2014-' + substring(ltrim(rtrim(@Qmonth)), 1, 3) + '-01')
出于我不确定的原因,您开始混用 select
语法。但请注意,您可以说 select <result> = <expr>
或 select <expr> as <result>
。 as
完全可选,但强烈推荐。
-- error
select from_dt as (select DATEADD(month,@StartMonth-1,DATEADD(year,@ac_year-1900,0)))
-- ok
select DATEADD(month, @StartMonth-1, DATEADD(year, cast(@ac_year-1900 as int), 0)) as from_dt
您尝试用 string/character 值进行减法时出现另一个错误。我想我得到的东西更接近你的想法,但我不保证这行代码是完全正确的。
接下来,您的论点在另一个片段中消失了。我相信您希望在第二个 set
的第 4 个位置有 3 个字符。 Substring()
的第三个参数需要是字符数长度而不是结束位置。所以使用 4, 3
而不是 5, 7
.
-- wrong part of the date
set @Endmonth =(select month('2014-'+substring(ltrim(rtrim(@Qmonth)),5,7)+'-01') as month2)
-- correct part of the date
set @Endmonth = month('2014-' + substring(ltrim(rtrim(@Qmonth)), 4, 3) + '-01')
这些更改应该会让您回到正确的轨道上,尽管您还没有达到必须在本季度末找到该月最后一天的地步。我会继续提供我自己的方法。
工作代码
declare @q int =
set @q = /* ignoring everything after the first three characters */
case lower(substring(@QMonth, 1, 3))
when 'jan' then 0 when 'apr' then 1 when 'jul' then 2 when 'oct' then 3
end;
declare @y int;
set @y = cast(left(@ac_year, 4) as int); /* assuming this contains a value like '2014-15' */
set @StartMonth = dateadd(quarter, @q, dateadd(year, @y - 2000, '2000-01-01');
set @EndMonth = dateadd(day, -1, dateadd(quarter, 1, @StartMonth));
您将需要查看输出参数以获取实际 return 两个日期值的过程。我让你自己处理。
您只需像这样传递年份参数 '2014-2015' 而不是 2014-15 和低于 sp 就可以了
create proc spQuarter
(
@YEAR VARCHAR(10),
@Quarter VARCHAR(10),
)
AS
BEGIN
DECLARE @QuarterId INT = (CASE
WHEN @Quarter = 'jan-mar' THEN 1
WHEN @Quarter = 'apr-jun' THEN 2
WHEN @Quarter = 'jul-sep' THEN 3
WHEN @Quarter = 'oct-dec' THEN 4
END)
DECLARE @PreYear VARCHAR(10) = (SELECT top 1 items from dbo.Split(@year,'-'))
DECLARE @NextYear VARCHAR(10)= (SELECT top 1 items from dbo.Split(@year,'-')
where items not in(SELECT top 1 items from dbo.Split(@year,'-')))
DECLARE @SDate Datetime
SET @SDate = (Case @QuarterId When 1 then CONVERT(Datetime,'01-01-'+ @NextYear )
when 2 then CONVERT(Datetime,'01-04-'+ @PreYear)
when 3 then CONVERT(Datetime,'01-07-'+ @PreYear)
when 4 then CONVERT(Datetime,'01-10-'+ @PreYear) end)
SELECT @SDate as StartDate ,DATEADD (dd, -1, DATEADD(qq, DATEDIFF(qq, 0, @SDate) +@QuarterId ,0)) as EndDate
END