【问题标题】:Finding sql date with account year and Quarter使用帐户年份和季度查找sql​​日期
【发布时间】:2016-01-05 14:47:12
【问题描述】:

我是 sql 新手,我面临一个问题 我需要创建存储过程,通过将 Quarters 作为字符串字符串和年份传递来返回任何季度的开始和结束日期

ex : 当我通过exec spname '2014-15','jul-sep' 时,它应该是七月的开始日期和九月的结束日期

【问题讨论】:

  • exec spname '2014-15','jul-sep' 为例,您期望什么结果?
  • 它应该将输出作为 7 月的开始日期和 9 月的结束日期返回
  • 请在您的问题中提供具体的输出 - 确切的值,而不是描述。
  • 当执行存储过程 t 它应该返回 01-07-2014 作为 startdateofquter 和 30-09-2014 作为 quter 的结束日期(sql 版本 2014)
  • 输入将始终正确,否则 SP 应该能够管理链接 exec spname '2014-15','aug-sep'exec spname '2014-15','jul-aug' 返回值 01-07-201430-09-2014

标签: sql sql-server tsql sql-date-functions sqldatetime


【解决方案1】:

不清楚您为什么不只提供年份和季度作为输入参数。以下过程应返回季度的开始和结束:

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

应该对输入参数进行一些额外的检查,但这应该是你需要的一个好的开始。

【讨论】:

  • 您知道dateadd() 也适用于宿舍吗?
  • @shawnt00 - 直到现在。感谢您指出。我已经更新了代码。
  • @Alexei 感谢您的帮助,但它不会起作用,它应该接受 2014-15 年
  • 那 15 对我来说没有任何意义。如果您以该特定形式收到年份,则可以定义 @year as VARCHAR(7) 并获取 @actualYear as CAST(SUBSTRING(@year, 4, 2) AS INT)
  • @Alexei 年将从 2014 年 4 月到 2015 年 3 月开始,所以当我通过 2014 年 1 月 15 日至 3 月(4 Quter)时,它应该返回 1 月的第一天和 3 月的最后一天2015
【解决方案2】:

您只需要传递这样的年份参数“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

【讨论】:

    【解决方案3】:

    评论

    首先介绍一下您的代码:

    没有理由在这些分配中使用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
    

    还有另一个错误,您尝试使用字符串/字符值进行减法运算。我想我的想法更接近你的想法,但我不保证那行代码会是完全正确的。

    接下来,你的论点在另一个 sn-p 中被取消了。我相信您希望在第二个set 的第四个位置有 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));
    

    您将需要查看输出参数以获取实际返回两个日期值的过程。我会让你自己处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多