Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 根据当前日期和配置的数据获取记录_Sql_Sql Server_Sql Server 2008 R2_Datediff - Fatal编程技术网

Sql 根据当前日期和配置的数据获取记录

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的配置。它可以在之前/之后发送。之

我正在致力于在我的web应用程序中实现短信发送部分的自动化

DurationType表存储是否应以小时、天、周、月为间隔发送sms。在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分钟一次

应考虑以下情况:

  • 小时,如果预订时间为当天上午10:15,如果预订时间在1小时之前,则为当天上午9:15

  • 天(24小时差异),如果预订时间为上午10:15第三天上午10:15,如果在SMS配置中配置为3天后

  • CREATE TABLE [dbo].[DurationType](
    [Id] [int] NOT NULL PRIMARY KEY,
    [DurationType] VARCHAR(10) NOT NULL
    )
    
  • 比赛周。如果预订时间为今天(星期三)上午10:15,那么如果在两周后配置,则在14天后的上午10:15

  • 月份的逻辑也和上面一样


  • 您似乎忘记了选择一些要返回的列

    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。