Отметить различия на уровне записи - PullRequest
0 голосов
/ 19 октября 2018

Настоящая головоломка прямо здесь.

Я хочу отметить переходы между де X1.Таким образом, переход из A -> B, B-> A и B-> C, C-> B.

Это сводит мой набор данных только к тем записям, у которых есть переход.

Конечной целью является вычисление дней между датой, когда в последний раз произошло X1 A, и первым, когда произошло X1 B.

Например:

ID1 -> Переход A вБ, даты 2018-01-20 и 2018-02-01.Тогда ответ должен быть х число дней между.

ИЛИ

Пример 2: ID1 -> Переход от А к В, даты 2018-02-16 и 2018-03-01.Тогда ответ должен быть х число дней между.

ID      X1      Date  
1       A       2018-01-01  
1       A       2018-01-20  
1       B       2018-02-01  
1       A       2018-02-15  
1       A       2018-02-16  
1       B       2018-03-01  
2       B       2018-01-01  
2       C       2018-03-05  
2       C       2018-03-06   
2       C       2018-03-08  
2       B       2018-03-20  

У меня уже есть этот цикл, но этот цикл занимает слишком много времени (0,3 секунды на запись):

DECLARE @Loop INT    
DECLARE @MAXROWS INT    
SET @Loop = 1    
SET @MAXROWS = (SELECT COUNT (*) FROM Y_Table)    
WHILE (@Loop <= @MAXROWS)    
BEGIN    
UPDATE Y_Table    
SET Y_Table.Test_MIN = (CASE WHEN     
(SELECT Y_Table.ID FROM Y_Table WHERE LIFE_CYCLE = @Loop) =   
(SELECT Y_Table.ID FROM Y_Table WHERE LIFE_CYCLE = @Loop + 1) AND  
(SELECT Y_Table.Date FROM Y_Table WHERE LIFE_CYCLE = @Loop) <   
(SELECT Y_Table.Date FROM Y_Table WHERE LIFE_CYCLE = @Loop + 1) AND  
(SELECT Y_Table.X1 FROM Y_Table WHERE LIFE_CYCLE = @Loop) <>   
(SELECT Y_Table.X1 FROM Y_Table WHERE LIFE_CYCLE = @Loop + 1)  
THEN '1' ELSE '0' END)  
FROM Y_Table  
WHERE   
LIFE_CYCLE = @Loop  
UPDATE Y_Table  
SET Y_Table.Test_MAX = (CASE WHEN   
(SELECT Y_Table.ID FROM Y_Table WHERE LIFE_CYCLE = @Loop) =   
(SELECT Y_Table.ID FROM Y_Table WHERE LIFE_CYCLE = @Loop + 1) AND  
(SELECT Y_Table.Date FROM Y_Table WHERE LIFE_CYCLE = @Loop) <   
(SELECT Y_Table.Date FROM Y_Table WHERE LIFE_CYCLE = @Loop + 1) AND  
(SELECT Y_Table.X1 FROM Y_Table WHERE LIFE_CYCLE = @Loop) <>   
(SELECT Y_Table.X1 FROM Y_Table WHERE LIFE_CYCLE = @Loop + 1)  
THEN '1' ELSE '0' END)  
FROM Y_Table  
WHERE   
LIFE_CYCLE = @Loop + 1  
PRINT @Loop  
SET @Loop = @Loop + 1  
END  

Как это решить?

Ответы [ 2 ]

0 голосов
/ 19 октября 2018
  • Используйте LEAD, чтобы получить следующую строку
  • Фильтр в другое место (= переход)

Примерно так

DECLARE @data table (ID int, X1 char(1), myDate  date)

INSERT @data VALUES (1, 'A', '2018-01-01'),  
    (1, 'A', '2018-01-20'),  
    (1, 'B', '2018-02-01'),  
    (1, 'A', '2018-02-15'),  
    (1, 'A', '2018-02-16'),  
    (1, 'B', '2018-03-01'),  
    (2, 'B', '2018-01-01'),  
    (2, 'C', '2018-03-05'),  
    (2, 'C', '2018-03-06'),   
    (2, 'C', '2018-03-08'),  
    (2, 'B', '2018-03-20');

WITH GetNextRows AS (
    SELECT
        *,
        NextX1 = LEAD (X1) OVER (PARTITION BY ID ORDER BY myDate),
        NextDate = LEAD (myDate) OVER (PARTITION BY ID ORDER BY myDate)
    FROM
        @data
    )
SELECT 
    *,
    Transation = CONCAT(X1, ' -> ', NextX1),
    DaysGap = DATEDIFF(DAY, myDate, NextDate)
FROM
    GetNextRows
WHERE
    NextX1 <> X1;


ID  X1  myDate  NextX1  NextDate    Transation  DaysGap
1   A   2018-01-20  B   2018-02-01  A -> B      12
1   B   2018-02-01  A   2018-02-15  B -> A      14
1   A   2018-02-16  B   2018-03-01  A -> B      13
2   B   2018-01-01  C   2018-03-05  B -> C      63
2   C   2018-03-08  B   2018-03-20  C -> B      12
0 голосов
/ 19 октября 2018

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

DECLARE @DataSource TABLE
(
    [ID] SMALLINT
   ,[X1] CHAR(1)
   ,[Date] DATE
);

INSERT INTO @DataSource ([ID], [X1], [Date])
VALUES ('1', 'A', '2018-01-01')
      ,('1', 'A', '2018-01-20')
      ,('1', 'B', '2018-02-01')
      ,('1', 'A', '2018-02-15')
      ,('1', 'A', '2018-02-16')
      ,('1', 'B', '2018-03-01')
      ,('2', 'B', '2018-01-01')
      ,('2', 'C', '2018-03-05')
      ,('2', 'C', '2018-03-06')
      ,('2', 'C', '2018-03-08')
      ,('2', 'B', '2018-03-20');

SELECT *
     ,IIF
     (
        [X1] <> LAG([X1], 1, NULL) OVER(PARTITION BY [ID] ORDER BY [Date] ASC)
       ,DATEDIFF(DAY, LAG([Date], 1, NULL) OVER(PARTITION BY [ID] ORDER BY [Date] ASC), [Date])
       ,NULL
    ) AS [TransitionInDays]
FROM @DataSource;

enter image description here

Обратите внимание, вам нужен SQL Server 2012+ для использования LAG.Дайте мне знать, если это не так.

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