SQL函数检查日期是不是在另一个表的2个日期之间

Posted

技术标签:

【中文标题】SQL函数检查日期是不是在另一个表的2个日期之间【英文标题】:SQL Function check if a date is between 2 dates from another tableSQL函数检查日期是否在另一个表的2个日期之间 【发布时间】:2018-10-11 07:00:54 【问题描述】:

我正在使用一个函数,该函数当前计算传入的两个日期之间的 SLA,它会检查 NULL 项并返回 0。

我现在需要考虑新表“NonBusinessDays”中的日期,并将这些日期从总 SLA 值中扣除。

我将如何检查两个传入的值是否包含其范围与其他表日期之间的任何日期,如果他们需要从 SLA 总数中删除该日期。

目前桌子是这样的;

CREATE TABLE #NonBusinessDays(
    [id] [uniqueidentifier] NOT NULL,
    [date] [date] NOT NULL,
    [name] [nvarchar](100) NOT NULL,
    [type] [nvarchar](50) NOT NULL)
GO

INSERT INTO #NonBusinessDays
           ([id]
           ,[date]
           ,[name]
           ,[type])
     VALUES
           ('1DF6A335-56F8-4DA7-B9C3-07DBAC9FBA8D'
           ,'2019-08-26'
           ,'Summer bank holiday'
           ,'PublicHoliday')

           ('0940FDC9-A875-48C5-BED8-0ABFA3AA5AE8',
            '2018-05-07',
            'Early May bank holiday',
            'PublicHoliday')
GO

所以我的函数是这样的;

CREATE FUNCTION dateSLA
(
@date1 DATETIME,
@date2 DATETIME
)
returns INT
AS 
BEGIN

declare @days INT
set @days = 0

      IF @date1 IS NULL AND @date2 IS NULL
            BEGIN
            GOTO Final
      END
      ELSE IF @date1 IS NOT NULL AND @date2 IS NOT NULL
      BEGIN


            SET @days = DATEDIFF(DAY, CONVERT(DATE, @date1, 103), CONVERT(DATE, @date2, 103))

            GOTO Final
      END

Final:

return @days

END
GO

我希望它检查 NonBusinessDays 表中的任何日期是否存在于传递给函数的参数之间,那么无论 SLA 需要多少天。

例如,如果在传入的参数之间存在 BusinessDays 的两个日期,那么这将取消 2。因此,SLA 计算为 10,但由于存在 2 个非工作日,这将使其变为 8。

任何指导都将不胜感激,如果您需要更多信息,请告诉我,我会修改。

【问题讨论】:

是否可以说服决定对非工作日建模的人改为使用完整的日历表(我的意思是,来一个,20 年的数据仍然少于 10000 行)?然后,您可以针对此表运行 COUNT(*),针对您的两个日期之间的所有日期,并标记为工作日。 不幸的是,在这种情况下它不能被更改,这个数据库归一个开发人员所有,我只需要与之合作......我知道......不是正常情况,但我必须妥协和使用我有什么选择。我不是要任何人在经过一些指导后专门为我写这个走向:) 很久没有看到 goto 语句了。这还不灭吗? :) 【参考方案1】:

我们可以大大减少这个功能并考虑到非工作日:

CREATE FUNCTION dateSLA
(
@date1 DATETIME,
@date2 DATETIME
)
returns INT
AS 
BEGIN

return COALESCE(
  DATEDIFF(day,@date1,@date2) -
  (select COUNT(*) from #NonBusinessDays
   where date between CAST(@date1 as date) and CAST(@date2 as date)),
  0)

END
GO

如果@date1@date2null,则datediff 将返回null,减法将留下null,最后合并将其变为0

DATEDIFF 计数 边界 两个 datetimes 之间的日期边界(午夜转换)和删除时间部分的相同值一样多。所以我们不需要它们作为dates 来调用DATEDIFF。我们确实需要这样来匹配开始日期的非工作日,因此我们将CAST 保留在那里,而且由于数据类型不匹配和对称性,我们对结束日期执行相同操作。

我忽略了当@date2 小于@date1 时会发生什么,这可能是这个函数的无效输入。

正如我在评论中所说,我更喜欢这里有一个完整的日历表,我们可以在工作日内执行 COUNT(*) 操作,但请理解此时您不可以选择。 (此时你开始质疑是否需要一个函数)

【讨论】:

感谢您的详细解释,您是正确的应用程序确定 date2 不能小于 date1 的验证。我将研究提供的答案,并通过几个测试运行它,看看它是如何工作的,这样我下次遇到这样的事情时可以更好地理解它。我更喜欢日历表,因为还有很多其他原因会使用它,所以我将在下次会议上挑战设计 - 我会很快回复。 这样就完美了,谢谢指导和解释。我已经看了一下,我已经将数据库链接到另一个新的分析数据库,我可以在此期间托管一个日历表。在我为这个建模之前,你对这张桌子的布局有什么建议吗?

以上是关于SQL函数检查日期是不是在另一个表的2个日期之间的主要内容,如果未能解决你的问题,请参考以下文章

检查日期是不是在另一个数据框中的两个日期之间,如果是则操作日期

检查给定日期是不是存在于从日期到今天之间

检查当前日期是不是在两个日期之间 Oracle SQL

如何从一个表中过滤出其 id 出现在另一个表的列中的记录

获取日期时间差异的异常

在 SQL 和 VB.NET 中检查日期是不是小于另一个