我正在尝试编写一个查询,查找与我公司一起庆祝月度周年纪念的用户,以便我们可以向他们发送电子邮件(即,如果今天的日期是3/27,则会找到注册的人无论年份如何,1 / 27,2 / 27,3 / 27,4 / 27等。
我的方法是找到其注册日期的“日”部分等于今天日期的“日”部分的用户。
SELECT [User Id],[Sign Up Date]
FROM [Monthly Account Update]
WHERE DATEPART(DAY,[Sign Up Date]) = DAY(GETDATE())
但是,这当然不适用于这些情况:
2月底,我没有机会通过电子邮件向29,30和31个月周年纪念日的人发送电子邮件,因为这不会发生。理想情况下,当它是2月28日时,我只想把29,30和31个日期的人混为一谈。
对于日期在30日结束的其他每个月,我都不会给第31个日期的人发送电子邮件。理想情况下,我只想把30和31个日期的人混在一起。
可以使用SQL查询完成其中任何一项吗?
答案 0 :(得分:1)
您需要一个更复杂的where
子句。这是一种蛮力方法:
SELECT [User Id],[Sign Up Date]
FROM [Monthly Account Update]
WHERE day([Sign Up Date]) = DAY(GETDATE()) or
(month(getdate()) in (4, 6, 9, 11) and day(getdate()) = 30 and DAY([Sign Up Date]) = 31) or
(month(getdate()) in (2) and day(getdate()) = 28 and DAY([Sign Up Date]) in (29, 30, 31))
如果它的feb,请寻找第28位。
答案 1 :(得分:1)
这里有一些复杂的答案!我们可以大大简化:
create function dbo.fnIsMonthlyAnniversary(
@startDate date,
@comparisonDate date
)
returns bit
as
begin
declare @retVal bit
set @retVal = 0
declare @deltaMonth int
set @deltaMonth = datediff( mm, @startDate, @comparisonDate )
if dateadd( mm, @deltaMonth, @startDate ) = @comparisonDate
begin
set @retVal = 1
end
return @retVal
end
-- usage:
select dbo.fnIsMonthlyAnniversary( '2012-12-31', CONVERT( date, getdate() ) )
供您使用:
SELECT [User Id],[Sign Up Date]
FROM [Monthly Account Update]
WHERE 1 = dbo.fnIsMonthlyAnniversary( [Sign Up Date], CONVERT( date, getdate() ) )
答案 2 :(得分:0)
尝试这样的事情:
创建一个永久表M,其中一列[months]填充了1到1000之间的整数,并使用如下查询:
SELECT [User Id],[Sign Up Date]
FROM [Monthly Account Update] AS U
JOIN M
ON CAST(getdate() AS DATE) = DATEADD(month,M.months,U.[Sign Up Date]
虽然效率不高,但对于少数员工来说,每天运行一次并不是问题。您还可以将M.months添加到SELECT列表中,并根据需要获得精确的周年纪念日数。
答案 3 :(得分:0)
减去一个月,并在最多4天的范围内包括每个后续日期,其中添加月份不会超过当前日期。
DECLARE @Today DATE = '2/28/2013';
SELECT [Current] = @Today, [MonthAgo] = DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))
FROM (VALUES(0),(1),(2),(3)) as t(v)
WHERE DATEADD(MONTH,1,DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))) <= @Today;
2013年2月28日的结果:
Current MonthAgo
---------- ----------
2013-02-28 2013-01-28
2013-02-28 2013-01-29
2013-02-28 2013-01-30
2013-02-28 2013-01-31
2013年3月27日的结果:
Current MonthAgo
---------- ----------
2013-03-27 2013-02-27
2013年4月30日的结果:
Current MonthAgo
---------- ----------
2013-04-30 2013-03-30
2013-04-30 2013-03-31
...等
修改强>
我的上述答案可以通过将其包装到CTE中然后以简单的方式加入原始查询来应用。请注意,对于整个查询,内联函数调用始终限制为四行,因此日期函数的性能影响应该可以忽略不计:
DECLARE @Today DATE = GETDATE();
; WITH CTE AS (
SELECT [Current] = @Today, [MonthAgo] = DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))
FROM (VALUES(0),(1),(2),(3)) as t(v)
WHERE DATEADD(MONTH,1,DATEADD(DAY,t.v,DATEADD(MONTH,-1,@Today))) <= @Today
)
SELECT [User Id],[Sign Up Date]
FROM [Monthly Account Update]
JOIN CTE ON CTE.[MonthAgo] = [Sign Up Date];
GO