我在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。
答案 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;日期为DATEADD
和DATEDIFF
。
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