SQL查询不返回所有行

时间:2015-02-18 16:17:15

标签: sql-server

我在SQL Server中有一个包含许多行的表,其中包含created_date列。此列包含从2006年开始的行。

我想获取在2015年2月及之前创建的所有行。此存储过程具有参数@month。它应该根据输入的@month值选择所有行。

这是我的问题:

select * 
from products 
where 1=1 
  and year(created_date) <= 2015 
  and month(created_date) <= @month 

但此查询仅返回在前一年的二月月中创建的记录排除在2014年其他月份创建的记录(例如,2014年 - 不包括03-17,2014-05-05。

我必须根据输入的@month获得新的约会。假设我进入7月份,我希望有条件&#34;其中created_date&lt; 2015年7月31日&#34 ;.所以我可以做这样的事情,

所以我改变了我的查询,

declare @date datetime
set @date = CAST((2015 + '-' + @month + '-' + 28) as datetime)
select * 
from products 
where 1=1 
and year(created_date) <= 2015 

但是这个查询返回1905-08-08 00:00:00.000并且我想得到2015-02-28 00:00:00.000而且我必须根据输入的@month找到总天数,这样我可以将该号码传递给CAST((2015 +&#39; - &#39; + @month +&#39; - &#39; + 28 )作为日期时间而不是28。

3 个答案:

答案 0 :(得分:3)

只需使用一个日期并指定created_date列必须小于该日期:

declare @newestDate datetime = '2015-03-01'

select * 
from products
where created_date < @newestDate

请注意,我将日期设置为3月1日,但在查询中我使用<而不是<=。这将处理包括时间分量的created_date值,例如, 2015-02-28 23:59:59

要生成“上一年的二月”的值,您实际上可能想要使用去年的当前月,如果是,您的日期将是:

declare @newestDate datetime = 
    DATEADD(year, -1, DATEADD(month, DATEDIFF(month, 0, GETDATE())+1, 0))

这将在下个月(即3月)开始工作,并且会使您的查询处于滚动月份。

答案 1 :(得分:1)

始终将日期/时间字段与可能的单个值进行比较 - 这也是性能最佳的。你可以&#34; round&#34;日期为DATEADDDATEDIFF

DECLARE @startOfNextMonth DATETIME;
SELECT @startOfNextMonth = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) + 1, 0);
select * from products where 1=1 and created_date < @startOfNextMonth;

转换日期的字符串操作也是可能的,但往往表现更差,并且很难做到正确。一般情况下,如果您想要&#34; round&#34;到了几年,几分钟,15秒的时间段,等等,这对字符串来说要困难得多。

如果可以,请重写您的存储过程,不要使用@month参数,而应考虑客户计算的绝对值 - 它更通用,并且更易于使用。然后,您的查询将简化为

select * from products where 1=1 and created_date < @limit;

当然,如果你必须使用@month,你可以在存储过程本身中构造这个偏移量:

DECLARE @limit DATETIME = 
    DATEFROMPARTS(DATEPART(YEAR, GETDATE()), @month, 1)
;

这利用了SQL Server 2012中引入的DATEFROMPARTS。对于以前的版本,可靠地构建日期相当混乱。有很多错误的方法可以在区域设置被设置为意外时破坏。 DATEADD再次提供帮助:

DECLARE @limit DATETIME = 
    DATEADD(MONTH, (DATEPART(YEAR, GETDATE()) - 1900) * 12 + @month - 1, 0)
;

这些不是构造日期时间值的唯一方法,但字符串操作无论如何都很棘手(因为在区域设置下唯一不会破坏的可靠格式是YYYYMMDD,没有破折号。)

答案 2 :(得分:0)

在这个问题中:Create a date with T-SQL您将看到如何在给定特定年份和月份的情况下构建sql-server日期数据类型。假设你打电话给那个&#39; my_date&#39;。

然后您就可以执行以下操作:

SELECT * FROM products WHERE created_date < my_date