Суммируйте дни в статусе системы, вычисляя разницу в днях для каждого набора записей - PullRequest
0 голосов
/ 16 января 2019

Я вычитаю дни между соответствующими датами, когда элемент находится в системном статусе. Формула, которую я использую, работает, когда есть только 2 записи, но часто их 3 или более. Означает ввод в статус и обновление из статуса и последовательное обновление обратно в статус и так далее. Все из которых имеют соответствующий код Stat, который будет одинаковым для любого соответствующего статуса и постепенно увеличивающиеся номера изменений (001,002,003, ...). У каждой из которых разные даты. Как вычислить разницу в днях между экземплярами 002 и 001, а затем сложить ее с разницей в 004 - 003.

SELECT 
    COUNT(*) as COUNT, 
    JCDS_SOGR.OBJNR, 
    JCDS_SOGR.STAT, 
    TJ30T.TXT30, 
    DIF = CASE
        WHEN COUNT(*) > 1 THEN DATEDIFF(DAY,MIN(JCDS_SOGR.UDATE),MAX(JCDS_SOGR.UDATE))
        WHEN COUNT(*) = 1 THEN DATEDIFF(DAY,MIN(JCDS_SOGR.UDATE),GETDATE())
    END
FROM
    JCDS_SOGR
    JOIN TJ30T 
        ON JCDS_SOGR.STAT = TJ30T.ESTAT
WHERE
    JCDS_SOGR.OBJNR = 'IE000000000010003137'
    AND TJ30T.SPRAS='E'
    AND TJ30T.MANDT='400'
    AND STSMA = 'VEHICLE'
GROUP BY
    JCDS_SOGR.OBJNR,
    JCDS_SOGR.STAT, 
    TJ30T.TXT30

Фактические результаты Разница сумм в днях разных наборов дат

Это образец данных для одного статуса и объекта, который имеет 7 записей:

MANDT   OBJNR              STAT    CHGNR UDATE    INACT CHIND
IE000000000010003137    E0004   001 20110815        I 400
IE000000000010003137    E0004   002 20130605    X   U 400
IE000000000010003137    E0004   003 20130913        U 400
IE000000000010003137    E0004   004 20150323    X   U 400
IE000000000010003137    E0004   005 20150512        U 400
IE000000000010003137    E0004   006 20151125    X   U 400
IE000000000010003137    E0004   007 20160927        U 400

Это Результат из моего кода Макс (20160927) - Мин (20110815):

COUNT    OBJNR              STAT    TXT30       DIF
7   IE000000000010003137    E0004   Operational 1870

Ожидаемые результаты ((002 -001) + (004-003) + (006-005) + (getdate () -007)): ​​

Это Какой должен быть результат в столбце Dif :

COUNT    OBJNR              STAT    TXT30       DIF
7   IE000000000010003137    E0004   Operational 2253

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Попробуйте запрос ниже.

    ;with cte
    AS
    (
        Select ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn,  
        *,
        LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
        COUNT(*) OVER(partition by STAT) As [Count]
        from YourTable
    )



    Select Max(rn) As [Count],
    OBJNR,STAT,
    SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE) 
            WHEN rn=[Count] THEN  DATEDIFF(d,UDATE,getDate())   
        ELSE 0 END)
    from cte
    Group BY OBJNR, STAT
0 голосов
/ 16 января 2019

Попробуй это, Эрика. Это должно дать вам достаточно, чтобы направить вас в правильном направлении. В SSMS вы можете запустить следующий T-SQL.

Я создал табличную переменную на основе вашего начального набора данных (это образец данных для одного состояния и объекта, который имеет 7 записей) вместо выборки фактических данных, поскольку у меня нет доступа к этому, очевидно. Я также сделал предположения о типах данных для этого примера.

-- Create table variable for the data --
DECLARE @data TABLE (
    MANDT VARCHAR(50)
    , OBJNR VARCHAR(50)
    , STAT VARCHAR(50)
    , CHGNR VARCHAR(3)
    , UDATE DATETIME
    , INACT VARCHAR(1)
    , CHIND VARCHAR(1)
);

-- Add the sample data --
INSERT INTO @data (
    MANDT, OBJNR, STAT, CHGNR, UDATE, INACT, CHIND
) VALUES
  ( '400', 'IE000000000010003137', 'E0004', '001', '20110815', '', 'I' )
, ( '400', 'IE000000000010003137', 'E0004', '002', '20130605', 'X', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '003', '20130913', '', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '004', '20150323', 'X', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '005', '20150512', '', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '006', '20151125', 'X', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '007', '20160927', '', 'U' );

Переменная таблицы @data содержит:

+-------+----------------------+-------+-------+-------------------------+-------+-------+
| MANDT |        OBJNR         | STAT  | CHGNR |          UDATE          | INACT | CHIND |
+-------+----------------------+-------+-------+-------------------------+-------+-------+
|   400 | IE000000000010003137 | E0004 |   001 | 2011-08-15 00:00:00.000 |       | I     |
|   400 | IE000000000010003137 | E0004 |   002 | 2013-06-05 00:00:00.000 | X     | U     |
|   400 | IE000000000010003137 | E0004 |   003 | 2013-09-13 00:00:00.000 |       | U     |
|   400 | IE000000000010003137 | E0004 |   004 | 2015-03-23 00:00:00.000 | X     | U     |
|   400 | IE000000000010003137 | E0004 |   005 | 2015-05-12 00:00:00.000 |       | U     |
|   400 | IE000000000010003137 | E0004 |   006 | 2015-11-25 00:00:00.000 | X     | U     |
|   400 | IE000000000010003137 | E0004 |   007 | 2016-09-27 00:00:00.000 |       | U     |
+-------+----------------------+-------+-------+-------------------------+-------+-------+

Затем я запросил данные, используя функции LEAD и LAG SQL Server (в производной таблице), чтобы посмотреть предыдущие или последующие значения UDATE для вычисления DATEDIFF.

-- Query for the desired resultset --
SELECT
    COUNT ( * ) AS [COUNT]
    , obj.OBJNR
    , obj.STAT
    , ( 'Operational' ) AS TXT30
    , SUM( obj.dif ) AS DIF
FROM (

    -- Query a DATEDIFF resultset --
    SELECT
        OBJNR
        , STAT
        , CASE INACT
            -- If the current record's INACT = X get the date difference between this and the PREVIOUS record using LAG.
            WHEN 'X' THEN DATEDIFF( DD, LAG( UDATE, 1, 0 ) OVER ( ORDER BY CHGNR ), UDATE )
            -- Otherwise, check if we are at the end of the resultset using LEAD...
            ELSE CASE LEAD( INACT, 1, '' ) OVER ( ORDER BY CHGNR )
                WHEN '' THEN DATEDIFF( DD, UDATE, GETDATE() )
                ELSE 0
            END
        END AS dif
    FROM @data

) AS obj
GROUP BY
    obj.OBJNR, obj.STAT;

Результат запроса:

+-------+----------------------+-------+-------------+------+
| COUNT |        OBJNR         | STAT  |    TXT30    | DIF  |
+-------+----------------------+-------+-------------+------+
|     7 | IE000000000010003137 | E0004 | Operational | 2253 |
+-------+----------------------+-------+-------------+------+

Обратите внимание на мое использование LEAD и LAG. В случае LEAD здесь, я смотрю, есть ли другая запись. Если его нет, то в этом случае, отмеченном LEAD, возвращающим пустую строку, мы достигли конца набора данных.

Третий параметр LEAD - это значение, возвращаемое в случае отсутствия данных для указанного условия. В этом случае я возвращаю пустую строку, в которой точка DATEDIFF вычисляется на основе текущей даты с использованием GETDATE (), поскольку нет другой записи для сравнения.

Если вы посмотрите на набор результатов для запроса производной таблицы, вы увидите:

+----------------------+-------+-------+-----+
|        OBJNR         | STAT  | INACT | dif |
+----------------------+-------+-------+-----+
| IE000000000010003137 | E0004 |       |   0 |
| IE000000000010003137 | E0004 | X     | 660 |
| IE000000000010003137 | E0004 |       |   0 |
| IE000000000010003137 | E0004 | X     | 556 |
| IE000000000010003137 | E0004 |       |   0 |
| IE000000000010003137 | E0004 | X     | 197 |
| IE000000000010003137 | E0004 |       | 840 |
+----------------------+-------+-------+-----+

Внешний SELECT просто суммирует значения [dif].

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

P.S. Вы можете прочитать больше о LAG: здесь и LEAD: здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...