упростить оператор SQL case в выражении case - PullRequest
0 голосов
/ 27 февраля 2020

Как бы я упростил это утверждение в T- SQL? Это обеспечивает желаемый результат, но это очень громоздко и трудно читать. Я должен использовать внутреннюю инструкцию case, чтобы преобразовать юлианскую дату (aka 6 di git число) в обычный формат даты.

В основном я делаю датировку (getdate (), инструкция case). Getdate () просто возвращает время (ie. 2/27/2020), а инструкция case преобразует юлианскую дату (ie. 123456) в обычную дату (ie, 01.01.2020).

Вот ожидаемый результат, если запрос был выполнен сегодня 27 февраля.

enter image description here

Select CASE 
        WHEN Datediff(day, Getdate(), CASE 
                    WHEN a.wadpl = 0
                        THEN NULL
                    ELSE Dateadd(d, Substring(Cast(wadpl AS VARCHAR(6)), 4, 3) - 1, CONVERT(DATETIME, CASE 
                                    WHEN LEFT(Cast(wadpl AS VARCHAR(6)), 1) = '1'
                                        THEN '20'
                                    ELSE '21'
                                    END + Substring(Cast(wadpl AS VARCHAR(6)), 2, 2) + '-01-01'))
                    END) < 0
            THEN 'Overdue Now'
        WHEN Datediff(day, Getdate(), CASE 
                    WHEN a.wadpl = 0
                        THEN NULL
                    ELSE Dateadd(d, Substring(Cast(wadpl AS VARCHAR(6)), 4, 3) - 1, CONVERT(DATETIME, CASE 
                                    WHEN LEFT(Cast(wadpl AS VARCHAR(6)), 1) = '1'
                                        THEN '20'
                                    ELSE '21'
                                    END + Substring(Cast(wadpl AS VARCHAR(6)), 2, 2) + '-01-01'))
                    END) <= 30
            THEN 'Coming due in 01-30 days'
        ELSE 'Not Overdue'
        END [Overdue Status]
FROM Table_X

1 Ответ

1 голос
/ 27 февраля 2020

Это легко понять, если предположить, что a.wadpl является целым числом:

SELECT CASE 
  WHEN DATEDIFF(DAY, GETDATE(), DATEADD(DAY, a.wadpl % 1000, DATEADD(YEAR,a.wadpl / 1000,'1899-12-31'))) <0 THEN 'Overdue now'
  WHEN DATEDIFF(DAY, GETDATE(), DATEADD(DAY, a.wadpl % 1000, DATEADD(YEAR,a.wadpl / 1000,'1899-12-31'))) <= 30 THEN 'Coming due in 01-30 days'
  ELSE 'Not Overdue'
  END [Overdue Status]
FROM Table_X

, или вы можете упростить, используя подзапрос (или вы можете использовать WITH):

SELECT CASE 
  WHEN Age <0 THEN 'Overdue now'
  WHEN Age <= 30 THEN 'Coming due in 01-30 days'
  ELSE 'Not Overdue'
  END [Overdue Status]
FROM (
  SELECT DATEDIFF(DAY,GETDATE(),
    DATEADD(DAY,wadpl%1000,DATEADD(YEAR,wadpl/1000,'1899-12-31'))) Age, * 
  FROM Table_X) a

Это, конечно, заставит вас сделать арифметику c для каждой строки, и вы не сможете легко использовать какие-либо индексы. Если бы вы спрашивали об агрегатах, я бы предложил сделать обратное, предварительно рассчитать даты и использовать их в своем запросе. Возможно, вы захотите добавить постоянный вычисляемый столбец в table_x:

ALTER TABLE TABLE_X
ADD wadpl_dt AS
  (DATEADD(DAY,wadpl%1000,DATEADD(YEAR,wadpl/1000,'1899-12-31'))) PERSISTED;

Теперь вы можете просто ссылаться на table_x.wadpl_dt всякий раз, когда вы хотите указать дату и время, и ваш запрос будет выглядеть так:

SELECT CASE 
  WHEN Age <0 THEN 'Overdue now'
  WHEN Age <= 30 THEN 'Coming due in 01-30 days'
  ELSE 'Not Overdue'
  END [Overdue Status]
FROM (
  SELECT DATEDIFF(DAY,GETDATE(), wadpl_dt) Age, * 
  FROM Table_X) a

Вот простой способ преобразовать дату в то, что вы называете юлианской датой:

SELECT (DATEPART(YEAR,GETDATE())-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE())

И вот как вы можете использовать ее:

DECLARE @overdue int;
DECLARE @next30 int;

SET @overdue = (SELECT (DATEPART(YEAR,GETDATE())-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE()));
SET @next30 = (SELECT (DATEPART(YEAR,GETDATE()+30)-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE()+30));
SELECT CASE 
  WHEN wadpl < @overdue THEN 'Overdue now'
  WHEN wadpl <= @next30 THEN 'Coming due in 01-30 days'
  ELSE 'Not Overdue'
  END [Overdue Status]
FROM Table_X
...