Выписка с помощью DATEADD для расчета более 24 часов - PullRequest
0 голосов
/ 15 декабря 2018

У меня небольшой кошмар с проектом на работе.Я извлекаю информацию из нашей системы составления списков с использованием 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 голосов
/ 15 декабря 2018

Помогает ли это указать вам правильное направление?

Я использую Общие табличные выражения ниже, чтобы подвести некоторые данные.

Эта версия может работать довольно страннозначения «time» в диапазоне от «24:00:00», а также значения «time» без начального нуля (например, «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

Надеюсь, это поможет

0 голосов
/ 15 декабря 2018

Предполагая, что ваше значение 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
0 голосов
/ 15 декабря 2018

Я пытался удалить этот ответ, но он не позволяет мне, поскольку он был принят.Так что я просто редактирую его, чтобы сказать, почему не следует использовать и в чем была моя ошибка , надеюсь, это также полезно:

Я предложилиспользуя замену, и это работает по значению, а не по позиции, поэтому, если бы у меня было время, равное '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
...