代码之家  ›  专栏  ›  技术社区  ›  Saajid Ismail

需要有关选择时段季度表中的日期范围的SQL查询的帮助

  •  1
  • Saajid Ismail  · 技术社区  · 14 年前

    我有张叫的桌子 时期 看起来像这样

    周期性的 γ 年期 γ 季刊

    7、2009、1

    8、2009、2

    9、2009、3

    10、2009、4

    11、2010、1

    12、2010、2

    表中的每一行表示一年中4个季度中的1个季度(如3个月的学期)。例如,第一行表示2009年第1期(即2009年1月1日至2009年3月31日的日期范围)。

    现在,我需要编写一个从上表中选择行/期间的查询,其中期间发生在两个日期范围之间,按照下面的伪代码。

    select *
    from Periods
    where Period is between @startDate and @endDate
    

    查询将在名为dbo.getPeriodsFromDateRange的表值函数内使用,并且@StartDate和@EndDate是该函数的参数。

    我被卡住了,不知道该怎么做。请帮忙。这适用于T-SQL(MS SQL Server 2000/2005)

    3 回复  |  直到 14 年前
        1
  •  5
  •   SQLMenace    14 年前

    尝试

    select *
    from Periods
    where  dateadd(qq,PeriodQuarter-1,dateadd(yy,PeriodYear -1900,0)) 
    between @startDate and @endDate
    
        2
  •  2
  •   momo    14 年前

    搜索而不是扫描是可能的:

    SELECT *
    FROM Periods
    WHERE
       PeriodYear BETWEEN Year(@startdate) AND Year(@enddate)
       AND PeriodYear * 4 + PeriodQuarter
          BETWEEN Year(@startdate) * 4 + DATEPART(Quarter, @startdate)
          AND Year(@startdate) * 4 + DATEPART(Quarter, @enddate)
    

    解释 :

    我将从年和季度这两个组成部分组成一个新的、按比例缩放的整数,将年和季度的每个组合视为一个数字。

    想象一下我是这样做的:

    AND PeriodYear + (PeriodQuarter - 1) / 4.0
       BETWEEN Year(@startdate) + (DATEPART(Quarter, @startdate) - 1) / 4.0
       AND Year(@startdate) + (DATEPART(Quarter, @enddate) - 1) / 4.0
    

    将我的原始表达式称为“mult”和这个新表达式为“div”,这里是一些年和季度,这些表达式的计算结果是:

    Year Qtr Div     Mult
    2009 1   2009.00 8037
    2009 2   2009.25 8038
    2009 3   2009.50 8039
    2009 4   2009.75 8040
    2010 1   2010.00 8041
    2010 2   2010.25 8042
    2010 3   2010.50 8043

    所以现在,如果我们对这些行运行一个WHERE子句:

    WHERE Div BETWEEN 2009.25 AND 2010.00
    

    您可以看到它将如何返回正确的行。mult版本的功能完全相同,只不过是增加了一年而不是减少了一个季度。我之所以使用它是因为整数数学和乘法比分数数学和除法更快。

    我使用两个条件(从一年开始)的原因是为了使查询具有可搜索性。我们想以一年为基础进行搜索,如果我们将它乘以4或在上面做其他数学运算,这是不可能的。所以我们先把扫描时间调整到合适的年份,然后对其进行微调,以消除不应该出现在结果中的任何季度。

    另一种选择是添加一个计算列并在其上放置索引。这不需要对代码插入或更新进行任何更改(只要它们正确地使用列列表),但可以让您根据需要进行常规的范围数学。

        3
  •  0
  •   barrylloyd    14 年前

    我想再在表中添加两列…

    起始日期 结束日期 -这些将存储每个期间的开始和结束日期(例如,在您的示例中,开始日期=2009年1月1日,结束日期=2009年3月31日)

    如果季度定义与您建议的不同,这将给您更多的灵活性。

    如果您这样做,那么查询就变得相当简单…

    select *
    from Periods
    where @startDate<Periods.StartDate and @endDate>Periods.EndDate
    

    假设您只希望包含完全封装在@startdate和@enddate之间的期间。如果你想要重叠的句点,那就试试……

    select *
    from Periods
    where @EndDate>Periods.StartDate and @StartDate<Periods.EndDate