TSQL - 获取月/年范围之间的所有结果

时间:2017-02-20 17:17:13

标签: sql tsql sql-server-2008-r2

我有一个接受以下参数的存储过程:

  1. 月起
  2. 年起
  3. 月到
  4. 年份
  5. 现在我的查询如下:

    SELECT      COL1, MyDate
    FROM        [dbo].[MyTable]
    WHERE       MONTH([MyDate]) >= @fromMonth
    AND         MONTH([MyDate]) <= @toMonth
    AND         YEAR([MyDate])  >= @fromYear
    AND         YEAR([MyDate])  <= @toYear
    GROUP BY    COL1, MyDate
    

    但是如果我使用参数运行查询:

    1. 月起= 9
    2. Year From = 2016
    3. 月到= 3
    4. 年至2017年
    5. 即使我有结果应该返回,我也没有结果。

2 个答案:

答案 0 :(得分:4)

对于sql server版本2012+,您可以使用DATEFROMPARTSEOMONTH

DECLARE @FromDate datetime, @ToDate datetime

SELECT  @FromDate = DATEFROMPARTS(@fromYear, @FromMonth, 1),
        @ToDate =  EOMONTH(DATEFROMPARTS(@ToYear, @ToMonth, 1)),

SELECT      COL1, MyDate
FROM        [dbo].[MyTable]
WHERE       [MyDate] >= @FromDate
AND         [MyDate] <= @ToDate
GROUP BY    COL1, MyDate

对于2012年之前的版本,您可以通过一些数学和演员来构建日期:

DECLARE @FromDate datetime, @ToDate datetime
SELECT  @FromDate = CAST(CAST(@FromYear * 10000 + @FromMonth * 100 + 1 as char(8)) as date),
        @ToDate =  DATEADD(MONTH, cast(CAST(@ToYear * 10000 + @ToMonth * 100 + 1 as char(8)) as date))
SELECT      COL1, MyDate
FROM        [dbo].[MyTable]
WHERE       [MyDate] >= @FromDate
AND         [MyDate] < @ToDate
GROUP BY    COL1, MyDate

请注意使用DateAdd获取@ToDate之后的第一天并使用<而不是<=

答案 1 :(得分:0)

因为你没有从你的桌子给我们一些样本数据,所以我自己创建了。

CREATE TABLE #Temp
    (
      MyCol VARCHAR(10)
    , MyDate DATETIME
    );
INSERT  INTO #Temp
        ( MyCol, MyDate )
VALUES  ( 'A', GETDATE() ),
        ( 'A', '2016-09-01' ),
        ( 'B', '2016-09-03' ),
        ( 'B', '2016-08-28' ),
        ( 'A', '2017-03-01' ),
        ( 'A', '2017-04-01' );

让我们取一个日期(2016-09-01)并将其分解。

您的WHERE子句有效地测试了第一行的以下条件。

  1. 9 >= 9 =&gt;真
  2. 9 <= 3 =&gt;假
  3. 2016 >= 2016 =&gt;真
  4. 2016 <= 2017 =&gt;真
  5. 因为您AND - 所有这些条件,您都不会返回您想要的结果。

    您需要将您的值评估为日期而不是数字,否则您将遇到这些问题。

    你可以这样做:

    DECLARE @ToDate AS DATE = CONVERT(DATE, CONVERT(VARCHAR, @toYear) + '-' + CONVERT(VARCHAR, @toMonth) + '-1');
    DECLARE @FromDate AS DATE = CONVERT(DATE, CONVERT(VARCHAR, @fromYear) + '-' + CONVERT(VARCHAR, @fromMonth) + '-1');
    
    SELECT  t.MyCol
          , t.MyDate
    FROM    #Temp AS t
    WHERE   t.MyDate BETWEEN @FromDate AND @ToDate
    GROUP BY t.MyCol
          , t.MyDate;
    

    这是一个很好的起点,但鉴于您提供的变量,您只能从2016-09-012017-04-01而非2016-09-012017-03-31获取数据。

    所以你需要再增加一个月。您可以通过多种方式执行此操作(在月份中添加一个,然后检查它是否超过13,DATEADD等。)

    我之所以选择DATEADD是因为它有点简单。

    你的最终结果如下:

    DECLARE @ToDate AS DATE = DATEADD(MONTH, 1, CONVERT(DATE, CONVERT(VARCHAR, @toYear) + '-' + CONVERT(VARCHAR, @toMonth) + '-1'));
    DECLARE @FromDate AS DATE = CONVERT(DATE, CONVERT(VARCHAR, @fromYear) + '-' + CONVERT(VARCHAR, @fromMonth) + '-1');
    
    SELECT  t.MyCol
          , t.MyDate
    FROM    #Temp AS t
    WHERE   t.MyDate >= @FromDate AND
            t.MyDate < @ToDate
    GROUP BY t.MyCol
          , t.MyDate;
    

    编辑:生成日期可能比做连接和转换更简洁。