Sql 根据当前日期和配置的数据获取记录
我正在致力于在我的web应用程序中实现短信发送部分的自动化 DurationType表存储是否应以小时、天、周、月为间隔发送sms。在SMS配置中引用Sql 根据当前日期和配置的数据获取记录,sql,sql-server,sql-server-2008-r2,datediff,Sql,Sql Server,Sql Server 2008 R2,Datediff,我正在致力于在我的web应用程序中实现短信发送部分的自动化 DurationType表存储是否应以小时、天、周、月为间隔发送sms。在SMS配置中引用 CREATE TABLE [dbo].[DurationType]( [Id] [int] NOT NULL PRIMARY KEY, [DurationType] VARCHAR(10) NOT NULL ) 预订表格包含原始预订数据。对于本次预订,我需要根据配置发送短信 短信配置。它定义了发送自动SMS的配置。它可以在之前/之后发送。之
CREATE TABLE [dbo].[DurationType](
[Id] [int] NOT NULL PRIMARY KEY,
[DurationType] VARCHAR(10) NOT NULL
)
预订表格包含原始预订数据。对于本次预订,我需要根据配置发送短信
短信配置。它定义了发送自动SMS的配置。它可以在之前/之后发送。之前=0,之后=1<代码>持续时间类型可以是小时=1,天=2,周=3,月=4
现在我需要根据SMS配置集找出当前需要发送SMS的预订列表
尝试使用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分钟一次
应考虑以下情况:
CREATE TABLE [dbo].[DurationType](
[Id] [int] NOT NULL PRIMARY KEY,
[DurationType] VARCHAR(10) NOT NULL
)
您似乎忘记了选择一些要返回的列
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
只需在DATEDIFF函数中交换日期即可 将日期差异(小时,B.StartTime,@currentTime)更改为日期差异(小时,B.StartTime)-仅限小时 因为你的一个返回值为负值(-1) 这很有效
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
列作为获取记录的列之一,您可以根据需要更改它您可以使用嵌套的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;
您可以在两个计划中实现自动化,一个用于获取每小时短信的预订详细信息,另一个用于获取每日/每周/每月预订详细信息。尝试:
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在(0)之前转换为-1,在(1)之后转换为1。因此,从BookingStartTime添加或减去时间
[编辑]
上述解决方案应按原样与您的数据模型配合使用。下面我建议通过更改数据模型来简化解决方案
选项1:元数据前后的更改
使用Before=-1
和After=1
代替Before=0
和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))
选项2:允许30天=1个月
在变更之前/之后,若30天的时间段足够表示一个月,则所有持续时间类型都可以转换为小时。问题是,您的客户对精度的要求有多高。如果你按照“三个月前”的规定休息一两天,我想你不会有太多抱怨
所以您的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)
尝试简化版本,删除Union和used 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
很抱歉更新。我的实际问题是基于配置集检索数据。不要硬编码小时和值1ah,这样做更有意义;)您可以指定要查看的结果吗?在给定的fiddle链接中,我删除了终止字符(
;
),将错误的别名更改为SMS,并在DATEDIFF中交换日期。它工作得很好,但不起作用。我试图复制粘贴您的代码,但出现了错误必须声明标量变量“@currentTime”
它只给出一条记录。在我的问题中看到我的预期结果。我需要基于天/周/月配置的其他记录:(已更新…请立即检查检查此项。您的回答是50%正确。但当我在SMS配置和预订表中添加一个条目时,它会显示更多记录。结果中不应显示第2、4、5、8行,因为它们不符合标准。
谢谢。但仍然第2行->不应显示,因为它有一个多小时(1天)
和第5行->现在不应该显示。但是当@currentTime为2014-07-12 10:15:00时它会显示。希望您能满足我的要求。SQL过程将每15分钟运行一次,并找到匹配的记录,以发送带有预期结果的SMSUpdated my question。检查它。它不仅基于小时,还基于月/日对于一次预订,我可能可以发送多条短信。比如一个小时前、两个小时后、一个月后、三个月后等等。你认为这个逻辑行得通吗?我认为我的最新编辑应该行得通,但你需要更多的数据来彻底测试它。如果你在as-1之前和之后存储,可能会更好。这样你就不必做额外的计算了。S30天可以被考虑1个月吗?如果是的话,那么在所有的持续时间类型中存储时间为1小时=1, 1天=24, 1周=24×7, 1月=24×7×30。