2017-02-20 74 views
0

我有接受下列参数的存储过程:TSQL - 获取月/年范围之间的所有结果

  1. 月从
  2. 年从
  3. 今年

现在我的查询看起来像这样:

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. 当月From = 9
  2. 起始年份= 2016
  3. 月= 3
  4. 一年= 2017年

即使我有应该返回的结果,我也没有得到任何结果。

+0

哇哈哇,这是混乱。请查看其扩展的TSQL文档。你正在让自己的生活比现在更难,因为有命令可以轻松做到这一点。 – user7568042

+4

你需要根据整个日期做标准。看看你的月份标准。数据中的月份必须大于9且小于3。你知道什么数字高于9且低于3? –

+1

你能提供你的模式和样本数据吗? http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-sql-query –

回答

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之后的月份的第一天,并使用<而不是<=

+0

您需要包含逻辑来确定ToMonth的最后一天是什么,否则您将无法获得结果中的整个月份。或者,您可以计算下一个月的时间,并将标准更改为

+2

@ChrisFlynn EOMONTH为您做到了。 –

+0

太棒了,我不知道! –

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 =>真
  2. 9 <= 3 =>假
  3. 2016 >= 2016 =>真
  4. 2016 <= 2017 =>真

因为你AND -ing所有这些条件,你'不会返回你想要的结果。

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

你可以做这样的事情:

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; 

编辑:有可能是生成日期比做级联和转换更清洁的方式。

相关问题