DATEADD的案例陈述,可进行超过24小时的计算

时间:2018-12-15 07:33:23

标签: sql case dateadd

我在做一个项目时有些噩梦。我正在使用SQL从我们的排班系统中获取信息。无论出于何种原因,排班系统都允许将呼叫转移创建为“ +0000-0700”。这将在24:00-31:00返回。

在测试SQL时,花了几天的时间才将这一事实确定为导致我痛苦的原因。一旦例行程序达到了这些转变之一,它就会发出“超出范围的错误”的提示,这在我发现问题的时候就变得更加有意义了!

但是,由于我需要处理代码中的怪异问题,所以它不像告诉某人更改其做法那样简单,因此不再需要24小时的班次,因此我希望手动将这些问题时间解释为我可以与。

以下行对我来说很有意义,但由于超出范围错误而失败:

SELECT
    RRP.shiftdate,
    CASE 
       WHEN RDS.SHIFTSTART > ‘23:59:59’ 
          THEN DATEADD(HOUR, -24, RDS.SHIFTSTART)
          ELSE RDS.SHIFTSTART
    END AS CLEANSED_SHIFTSTART
...

但是,它崩溃并显示此错误:

  

将varchar数据类型转换为日期时间数据类型会导致超出范围的值

该函数的哪个部分在抱怨?

CASE WHEN RDS.SHIFTSTART > ‘23:59:59’ THEN ‘ABOVE 24H’

这很好用,但是我无法在DATEADD上解决问题,因为我已经在代码中的其他地方成功使用了它。

3 个答案:

答案 0 :(得分:1)

我试图删除此答案,但由于被接受,它没有让我。因此,我只是在编辑它,以说明为什么不应使用以及我的错误是什么,我希望它也有用:

我建议使用replace,并且该替换按值而不是位置起作用,因此,如果我的时间是“ 28:59:28”,则实际上它将更改为04:59:4

我错误地建议的解决方案是:

考虑到您使用的是字符串,这应该可以解决问题:

SELECT CASE WHEN RDS.SHIFTSTART > '23:59:59' THEN 
                    CASE WHEN (CAST(LEFT(RDS.SHIFTSTART,2) AS INT)%24) < 10
                         THEN '0'+ REPLACE(RDS.SHIFTSTART,LEFT(RDS.SHIFTSTART,2),(CAST(LEFT(RDS.SHIFTSTART,2) AS INT)%24))
                    ELSE REPLACE(RDS.SHIFTSTART,LEFT(RDS.SHIFTSTART,2), (CAST(LEFT(RDS.SHIFTSTART,2) AS INT)%24) )
                    END
       ELSE RDS.SHIFTSTART
       END AS Cleansed_ShiftStart

这将持续任何小时,因此,如果您的班次从“ 49:34:54”开始,则应为“ 01:34:54”

但是,如果移位最多为+7,那么您可以简单地这样做:

    SELECT CASE WHEN RDS.SHIFTSTART > '23:59:59' 
                THEN '0'+ REPLACE(RDS.SHIFTSTART,LEFT(RDS.SHIFTSTART,2),(CAST(LEFT(RDS.SHIFTSTART,2) AS INT)%24))                     
                ELSE RDS.SHIFTSTART
           END AS Cleansed_ShiftStart

答案 1 :(得分:1)

假设您的shiftstart值始终以两位数字开头,则可以将前两位数字替换为数字模数24:

select stuff(rds.shiftstart, 1, 2,
             left(rds.shiftstart, 2) % 24
            ) as cleansed_shiftstart

这不会将值转换为时间;如果您愿意,那么转换将是安全的。

不喜欢隐式转换,我可以明确地写:

select stuff(rds.shiftstart, 1, 2,
             try_convert(int, left(rds.shiftstart, 2)) % 24
            ) as cleansed_shiftstart

答案 2 :(得分:0)

此帮助是否将您指向正确的方向?

我在下面使用Common Table Expressions来伪造一些数据。

此版本可以处理范围在“ 24:00:00”范围内的相当奇怪的“时间”值,以及没有前导零的“时间”值(例如“ 7:00:00”)。

WITH s1
as
(
SELECT '31:50:12' as SHIFTSTART
       ,CAST(LEFT('31:50:12', CHARINDEX(':','31:50:12') - 1) as int) as my_hours_parsed
       ,SUBSTRING('31:50:12', CHARINDEX(':','31:50:12'), 10) as my_min_sec
UNION
SELECT '21:15:23' as SHIFTSTART
       ,CAST(LEFT('21:15:23', CHARINDEX(':','21:15:23') - 1) as int) as my_hours_parsed
       ,SUBSTRING('21:15:23', CHARINDEX(':','21:15:23'), 10) as my_min_sec
UNION
SELECT '7:00:00' as SHIFTSTART
       ,CAST(LEFT('7:00:00', CHARINDEX(':','7:00:00') - 1) as int) as my_hours_parsed
       ,SUBSTRING('7:00:00', CHARINDEX(':','7:00:00'), 10) as my_min_sec
UNION
SELECT '49:00:00' as SHIFTSTART
       ,CAST(LEFT('49:00:00', CHARINDEX(':','49:00:00') - 1) as int) as my_hours_parsed
       ,SUBSTRING('49:00:00', CHARINDEX(':','49:00:00'), 10) as my_min_sec
UNION
SELECT '99:23:00' as SHIFTSTART
       ,CAST(LEFT('99:23:00', CHARINDEX(':','99:23:00') - 1) as int) as my_hours_parsed
       ,SUBSTRING('99:23:00', CHARINDEX(':','99:23:00'), 10) as my_min_sec
UNION
SELECT '157:23:00' as SHIFTSTART
       ,CAST(LEFT('157:23:00', CHARINDEX(':','157:23:00') - 1) as int) as my_hours_parsed
       ,SUBSTRING('157:23:00', CHARINDEX(':','157:23:00'), 10) as my_min_sec           

)
SELECT s1.SHIFTSTART
      ,s1.my_hours_parsed
      ,s1.my_min_sec
      ,CASE WHEN s1.my_hours_parsed > 24 
            THEN 'Houston, we have a problem' 
            ELSE 'Works for me'
            END as SHIFTSTART_profile
      ,CAST(s1.my_hours_parsed - 24*(s1.my_hours_parsed/24) AS varchar(2)) + s1.my_min_sec as my_time_mod             
FROM s1;

这是结果...

    SHIFTSTART  my_hours_parsed my_min_sec  SHIFTSTART_profile              my_time_mod
1   157:23:00   157             :23:00      Houston, we have a problem      13:23:00
2   21:15:23    21              :15:23      Works for me                    21:15:23
3   31:50:12    31              :50:12      Houston, we have a problem      7:50:12
4   49:00:00    49              :00:00      Houston, we have a problem      1:00:00
5   7:00:00     7               :00:00      Works for me                    7:00:00
6   99:23:00    99              :23:00      Houston, we have a problem      3:23:00

希望这会有所帮助