我正致力于在我的网络应用程序中自动化SMS发送部分。
DurationType 表存储短信是否应以小时,天,周,月的间隔发送。在SMSConfiguration中引用
CREATE TABLE [dbo].[DurationType](
[Id] [int] NOT NULL PRIMARY KEY,
[DurationType] VARCHAR(10) NOT NULL
)
预订表包含原始预订数据。对于此预订,我需要根据配置发送短信。
短信配置。其中定义了发送自动SMS的配置。它可以在之前/之后发送。在= 0之前,之后= 1。 DurationType can be Hours=1, Days=2, Weeks=3, Months=4
现在我需要根据短信配置集找出需要在当前时间发送短信的预订列表。
使用UNION审核SQL
DECLARE @currentTime smalldatetime = '2014-07-12 11:15:00'
-- 'SMS CONFIGURED FOR HOURS BASIS'
SELECT B.Id AS BookingId,
B.StartTime AS BookingStartTime,@currentTime As CurrentTime, SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
WHERE (DATEDIFF(HOUR, @currentTime, B.StartTime) = SMS.Duration AND SMS.DurationType=1 AND BeforeAfter=0)
OR
(DATEDIFF(HOUR, B.StartTime, @currentTime) = SMS.Duration AND SMS.DurationType=1 AND BeforeAfter=1)
--'SMS CONFIGURED FOR DAYS BASIS'
UNION
SELECT B.Id AS BookingId,
B.StartTime AS BookingStartTime,@currentTime As CurrentTime, SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
WHERE (DATEDIFF(DAY, @currentTime, B.StartTime) = SMS.Duration AND SMS.DurationType=2 AND BeforeAfter=0)
OR
(DATEDIFF(DAY, B.StartTime, @currentTime) = SMS.Duration AND SMS.DurationType=2 AND BeforeAfter=1)
--'SMS CONFIGURED FOR WEEKS BASIS'
UNION
SELECT B.Id AS BookingId,
B.StartTime AS BookingStartTime, @currentTime As CurrentTime, SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
WHERE (DATEDIFF(DAY, @currentTime, B.StartTime)/7 = SMS.Duration AND SMS.DurationType=3 AND BeforeAfter=0)
OR
(DATEDIFF(DAY, B.StartTime, @currentTime)/7 = SMS.Duration AND SMS.DurationType=3 AND BeforeAfter=1)
--'SMS CONFIGURED FOR MONTHS BASIS'
UNION
SELECT B.Id AS BookingId,
B.StartTime AS BookingStartTime, @currentTime As CurrentTime, SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
WHERE (dbo.FullMonthsSeparation(@currentTime, B.StartTime) = SMS.Duration AND SMS.DurationType=4 AND BeforeAfter=0)
OR
(dbo.FullMonthsSeparation(B.StartTime, @currentTime) = SMS.Duration AND SMS.DurationType=4 AND BeforeAfter=1)
结果
问题:
SQL过程每15分钟运行一次。当前查询保持返回天数/周/月记录,即使是当前时间' 2014-07-12 11:30:00' 2014-07-12 11:45:00'等等
我想要一个单独的查询来处理所有小时/天/周/月 计算,我应该只有一次见面记录 正确的时间。否则我会一次又一次地发送短信 每隔15分钟,每天/每周/月记录匹配。
应考虑以下方案。
小时,如果预订时间是10:15。当天上午9:15,如果是在配置1小时之前,则为A.M.
日(24小时差异),如果预订时间是10:15 A.M第3天早上10:15 A.M如果在SMSConfiguration中3天后配置
比赛周。如果预订时间是今天(星期三)上午10:15,那么14天后早上10:15,如果在2周后配置,则预订。
月也和上面的逻辑相同。
答案 0 :(得分:2)
尝试使用简化版FIDDLE,删除Union并使用OR条件
小时列表 - 每15分钟跑一次
DECLARE @currentTime smalldatetime = '2014-07-12 11:15:00'
SELECT B.Id AS BookingId, C.Id, C.Name,
B.StartTime AS BookingStartTime,@currentTime As CurrentTime, SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
LEFT JOIN Category C ON C.Id=B.CategoryId
WHERE
(DATEDIFF(MINUTE, @currentTime, B.StartTime) = SMS.Duration*60 AND SMS.DurationType=1 AND BeforeAfter=0)
OR
(DATEDIFF(MINUTE, B.StartTime, @currentTime) = SMS.Duration*60 AND SMS.DurationType=1 AND BeforeAfter=1)
Order BY B.Id
GO
每天/每周/每月上市 - 每天早上一次运行
DECLARE @currentTime smalldatetime = '2014-07-12 08:00:00'
SELECT B.Id AS BookingId, C.Id, C.Name,
B.StartTime AS BookingStartTime,@currentTime As CurrentTime, SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
LEFT JOIN Category C ON C.Id=B.CategoryId
WHERE
(((DATEDIFF(DAY, @currentTime, B.StartTime) = SMS.Duration AND SMS.DurationType=2)
OR (DATEDIFF(DAY, @currentTime, B.StartTime) = SMS.Duration*7 AND SMS.DurationType=3)
OR (DATEDIFF(DAY, @currentTime, B.StartTime) = SMS.Duration*30 AND SMS.DurationType=4))
AND BeforeAfter=0)
OR
(((DATEDIFF(DAY, B.StartTime, @currentTime) = SMS.Duration AND SMS.DurationType=2)
OR (DATEDIFF(DAY, @currentTime, B.StartTime) = SMS.Duration*7 AND SMS.DurationType=3)
OR (DATEDIFF(DAY, @currentTime, B.StartTime) = SMS.Duration*30 AND SMS.DurationType=4))
AND BeforeAfter=1)
Order BY B.Id
答案 1 :(得分:0)
您似乎忘记选择要返回的列。
DECLARE @currentTime smalldatetime = '2014-07-12 09:15:00';
SELECT [col1], [col2], [etcetera]
FROM
Bookings B
INNER JOIN SMSConfiguration SMS ON SMS.CategoryId=B.CategoryId
WHERE DATEDIFF(hour,B.StartTime,@currentTime)=1
答案 2 :(得分:0)
只需swap the dates in DATEDIFF
功能
将 DATEDIFF(小时,B.StartTime,@ currentTime)更改为 DATEDIFF(小时,@ currentTime,B.StartTime) - 仅限HOUR
因为你的一个会返回否定( - 1)中的值。
DECLARE @currentTime smalldatetime = '2014-07-12 09:15:00'
SELECT B.Id AS BookingId, @currentTime AS CurrentTime,
B.StartTime AS BookingStartTime, SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
WHERE (SMS.CategoryId IS NOT NULL AND
DATEDIFF(HOUR, @currentTime, B.StartTime) = SMS.Duration) OR
(SMS.CategoryId IS NULL AND
(DATEDIFF(DAY, B.StartTime, @currentTime) = SMS.Duration OR
DATEDIFF(MONTH, B.StartTime, @currentTime) = SMS.Duration))
答案 3 :(得分:0)
这有效
DECLARE @currentTime smalldatetime
set @currentTime= '2014-07-12 09:15:00'
SELECT B.CategoryId FROM
Bookings B
INNER JOIN SMSConfiguration SMS ON SMS.CategoryId=B.CategoryId
WHERE DATEDIFF(hh,B.StartTime,@currentTime)=1
你的sql小提琴有两个问题
1)您没有设置currentTime
2)你的select语句中有列
注意:我将B.CategoryId
作为获取记录的列之一,您可以根据您的要求进行更改
答案 4 :(得分:0)
您可以使用嵌套的CASE表达式在单个查询中实现结果。请试试这个,
DECLARE @currentTime smalldatetime = '2014-07-12 11:15:00'
SELECT B.Id AS BookingId,
SMS.Duration,
B.StartTime AS BookingStartTime,
@currentTime As CurrentTime,
SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS
ON SMS.CategoryId = B.CategoryId
OR SMS.CategoryId IS NULL
WHERE
SMS.Duration =
CASE
WHEN SMS.DurationType = 1 THEN --'SMS CONFIGURED FOR HOURS BASIS'
CASE WHEN BeforeAfter = 0 THEN
DATEDIFF(HOUR, @currentTime, B.StartTime)
ELSE
DATEDIFF(HOUR, B.StartTime, @currentTime)
END
WHEN SMS.DurationType = 2 THEN --'SMS CONFIGURED FOR DAY BASIS'
CASE WHEN BeforeAfter = 0 THEN
DATEDIFF(DAY, @currentTime, B.StartTime)
ELSE
DATEDIFF(DAY, B.StartTime, @currentTime)
END
WHEN SMS.DurationType = 3 THEN --'SMS CONFIGURED FOR WEEK BASIS'
CASE WHEN BeforeAfter = 0 THEN
DATEDIFF(DAY, @currentTime, B.StartTime)/7
ELSE
DATEDIFF(DAY, B.StartTime, @currentTime)/7
END
ELSE
CASE WHEN BeforeAfter = 0 THEN -- 'SMS CONFIGURED FOR MONTH BASIS'
dbo.FullMonthsSeparation(@currentTime, B.StartTime)
ELSE
dbo.FullMonthsSeparation(B.StartTime, @currentTime)
END
END
ORDER BY BOOKINGID;
您可以自动完成两个时间表,一个用于获取每小时短信的预订详情,另一个用于每日/每周/每月预订详细信息。
答案 5 :(得分:0)
尝试:
DECLARE @currentTime smalldatetime = '2014-07-12 09:15:00'
SELECT B.Id AS BookingId,
B.StartTime AS BookingStartTime,
@currentTime CURRENT_DT,
SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
WHERE ( SMS.DurationType = 1
AND @currentTime = DATEADD(HOUR, (2*SMS.BeforeAfter-1)*SMS.Duration, B.StartTime))
OR
( SMS.DurationType = 2
AND @currentTime = DATEADD(DAY, (2*SMS.BeforeAfter-1)*SMS.Duration, B.StartTime))
OR
( SMS.DurationType = 3
AND @currentTime = DATEADD(WEEK, (2*SMS.BeforeAfter-1)*SMS.Duration, B.StartTime))
OR
( SMS.DurationType = 4
AND @currentTime = DATEADD(MONTH, (2*SMS.BeforeAfter-1)*SMS.Duration, B.StartTime))
2 * SMS.BeforeAfter-1将Before(0)转换为-1,将After(1)转换为1.因此,在BookingStartTime中添加或减去时间
<强> [编辑] 强>
上述解决方案应该与您的数据模型一起使用。下面我建议通过更改数据模型来简化解决方案。
http://sqlfiddle.com/#!3/6e9e9/1
使用Before = 0
和After = 1
,而不是Before = -1
和After = 1
。然后这些可以用来改变任何日期偏移的方向
例如:
INSERT INTO [dbo].[SMSConfiguration]
([CategoryId],[SMSText],[BeforeAfter],[Duration],[DurationType],[IsActive])
VALUES
(1,'Before 1 hour',-1,1,1,1)--
INSERT INTO [dbo].[SMSConfiguration]
([CategoryId],[SMSText],[BeforeAfter],[Duration],[DurationType],[IsActive])
VALUES
(NULL,'After 1 hour (no category id))',1,1,1,1)
更新了查询:
DECLARE @currentTime smalldatetime = '2014-07-12 09:15:00'
SELECT B.Id AS BookingId,
B.StartTime AS BookingStartTime,
@currentTime CURRENT_DT,
SMS.SMSText
FROM Bookings B INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
WHERE ( SMS.DurationType = 1
AND @currentTime = DATEADD(HOUR, SMS.BeforeAfter*SMS.Duration, B.StartTime))
OR
( SMS.DurationType = 2
AND @currentTime = DATEADD(DAY, SMS.BeforeAfter*SMS.Duration, B.StartTime))
OR
( SMS.DurationType = 3
AND @currentTime = DATEADD(WEEK, SMS.BeforeAfter*SMS.Duration, B.StartTime))
OR
( SMS.DurationType = 4
AND @currentTime = DATEADD(MONTH, SMS.BeforeAfter*SMS.Duration, B.StartTime))
http://sqlfiddle.com/#!3/808cd/1
在更改之前/之后,如果30天的时间足以表示一个月,那么所有持续时间类型都可以转换为小时。问题是您的客户在精确度方面的具体程度。如果你在“3个月前”规则的一两天内离开,我认为你不会有很多抱怨。
所以你的DurationType表看起来像这样
CREATE TABLE [dbo].[DurationType](
[Id] [int] NOT NULL PRIMARY KEY,
[DurationType] VARCHAR(10) NOT NULL,
[HourConversion] [int] NOT NULL
)
GO
INSERT INTO [dbo].[DurationType]([Id],[DurationType],[HourConversion])
VALUES(1,'Hours',1)
INSERT INTO [dbo].[DurationType]([Id],[DurationType],[HourConversion])
VALUES(2,'Days',24)
INSERT INTO [dbo].[DurationType]([Id],[DurationType],[HourConversion])
VALUES(3,'Weeks',24*7)
INSERT INTO [dbo].[DurationType]([Id],[DurationType],[HourConversion])
VALUES(4,'Months',24*30)
通过这些更改,可以将查询修改为:
DECLARE @currentTime smalldatetime = '2014-07-12 09:15:00'
SELECT B.Id AS BookingId,
B.StartTime AS BookingStartTime,
@currentTime CURRENT_DT,
SMS.SMSText
FROM Bookings B
INNER JOIN
SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId OR SMS.CategoryId IS NULL
INNER JOIN
DurationType DT ON DT.Id = SMS.DurationType
WHERE @currentTime = DATEADD(HOUR, SMS.BeforeAfter*SMS.Duration*DT.HourConversion, B.StartTime)