Подсчет увеличения в серии с изменением параметров для каждого ID - PullRequest
3 голосов
/ 31 мая 2019

У меня есть набор данных, который имеет 12 различных значений для идентификатора, а также начальные и конечные значения. То, что я хочу инициализировать, это взять начальное значение в качестве начального аргумента цикла и конечное значение в качестве последнего аргумента. Поиск значений корыта в соответствии с ними, и найти первое последовательное увеличение.

Ниже я опубликовал пример набора данных:

create table #sample_data(
ID  VARCHAR(10), val1 INT, val2 INT, val3 INT, val4 INT, val5 INT, val6 INT, val7 INT, val8 INT, val9 INT, val10 INT, val11 INT, val12 INT, startValue INT, endValue INT  
);

insert into #sample_data values
    (1001,3,2,1,0,1,2,3,0,0,0,0,0,1,7),
    (1002,1,2,3,4,0,0,0,1,2,3,0,0,1,12),
    (1003,0,3,2,1,0,0,0,0,0,0,0,0,1,12),
    (1004,0,1,2,3,4,0,0,0,0,0,0,0,3,9),
    (1005,1,1,1,1,2,3,2,2,1,1,0,0,1,8);

Вот результат, который я ожидаю: для идентификатора = 1001 мое начальное значение равно 1, а конечное значение равно 7, алгоритм переходит от val1 к val7, чтобы сравнить каждое значение val со следующим и считать увеличение до его окончания. В этом случае для 1001 это будет 0, так как серии начнутся с уменьшения. для ID 1002 это также будет 3 (от val1 до val4 и остановится на val5, когда произойдет уменьшение) для ID 1003 это будет 1, так как в начале наблюдается только увеличение для ID 1004 это будет 2, так как начинается с 3 и заканчивается в val9 для ID 1005 это будет 2, что является увеличением от val4 до val6

Я пытался выполнить это с записью CURSOR, но, поскольку у меня было более 300K строк данных, выполнение заняло несколько часов. Если у вас есть предложение получше (без использования курсора), я буду очень рад.

Ответы [ 2 ]

1 голос
/ 02 июня 2019

Вы можете попробовать следующий подход. Основная часть заключается в том, что каждая строка преобразуется в таблицу из 12 строк с дополнительным столбцом Increase и соответствующим предложением WHERE.

Введите:

CREATE TABLE #SampleData(
   ID VARCHAR(10),
   val1 INT,
   val2 INT,
   val3 INT,
   val4 INT,
   val5 INT,
   val6 INT,
   val7 INT,
   val8 INT,
   val9 INT,
   val10 INT,
   val11 INT,
   val12 INT,
   startValue INT,
   endValue INT
);

INSERT INTO #SampleData
   (ID,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12,startValue,endValue)
VALUES
   (1001,3,2,1,0,1,2,3,0,0,0,0,0,1,7),
   (1002,1,2,3,4,0,0,0,1,2,3,0,0,1,12),
   (1003,0,3,2,1,0,0,0,0,0,0,0,0,1,12),
   (1004,0,1,2,3,4,0,0,0,0,0,0,0,3,9),
   (1005,1,1,1,1,2,3,2,2,1,1,0,0,1,8),
   (1006,1,2,3,4,4,0,7,0,9,10,0,12,1,12)

T-SQL:

;WITH PreparationCTE AS (
    SELECT
       s.ID,
       v.Increase,
       ROW_NUMBER() OVER (PARTITION BY s.ID ORDER BY v.Nmr) AS Rn1,
       SUM(CASE WHEN v.Increase = -1 THEN 0 ELSE 1 END) OVER (PARTITION BY s.ID ORDER BY v.Nmr) AS Rn2
    FROM #SampleData s
    CROSS APPLY (VALUES
       (1,  Val1,  CASE WHEN Val1 < Val2   THEN 1 WHEN Val1 = Val2   THEN 0 ELSE -1 END),
       (2,  Val2,  CASE WHEN Val2 < Val3   THEN 1 WHEN Val2 = Val3   THEN 0 ELSE -1 END),
       (3,  Val3,  CASE WHEN Val3 < Val4   THEN 1 WHEN Val3 = Val4   THEN 0 ELSE -1 END),
       (4,  Val4,  CASE WHEN Val4 < Val5   THEN 1 WHEN Val4 = Val5   THEN 0 ELSE -1 END),
       (5,  Val5,  CASE WHEN Val5 < Val6   THEN 1 WHEN Val5 = Val6   THEN 0 ELSE -1 END),
       (6,  Val6,  CASE WHEN Val6 < Val7   THEN 1 WHEN Val6 = Val7   THEN 0 ELSE -1 END),
       (7,  Val7,  CASE WHEN Val7 < Val8   THEN 1 WHEN Val7 = Val8   THEN 0 ELSE -1 END),
       (8,  Val8,  CASE WHEN Val8 < Val9   THEN 1 WHEN Val8 = Val9   THEN 0 ELSE -1 END),
       (9,  Val9,  CASE WHEN Val9 < Val10  THEN 1 WHEN Val9 = Val10  THEN 0 ELSE -1 END),
       (10, Val10, CASE WHEN Val10 < Val11 THEN 1 WHEN Val10 = Val1  THEN 0 ELSE -1 END),
       (11, Val11, CASE WHEN Val11 < Val12 THEN 1 WHEN Val11 = Val2  THEN 0 ELSE -1 END),
       (12, Val12, 0)
    ) v(Nmr, Val, Increase)
    WHERE (s.startValue <= v.Nmr) AND (v.Nmr <= s.endValue)
)
SELECT ID, SUM(CASE WHEN (Increase >= 0) AND (Rn1 = Rn2) THEN Increase ELSE 0 END) AS [Count]
FROM PreparationCTE
GROUP BY ID
ORDER BY ID

Выход:

----------
ID  Count
----------
1001    0
1002    3
1003    1
1004    2
1005    2
1006    3
0 голосов
/ 31 мая 2019

Если я правильно понял, к чему вы стремитесь, вы можете сделать это, выбрав следующий случай:

select result.Id, 
    -- result.resulttext
    LEN(replace(substring(result.resulttext,1, charindex('0', result.resulttext)-1), '1', '')) as finaltesult
    from
    (select ID, 
        case when S.val1 <= S.val2   then case when S.val2  >= S.startvalue and S.val2  <= S.endvalue then case when S.val1 < S.val2 then '2' else '1' end else '1' end else '0' end +
        case when S.val2 <= S.val3   then case when S.val3  >= S.startvalue and S.val3  <= S.endvalue then case when S.val2 < S.val3 then '2' else '1' end  else '1' end else '0' end + 
        case when S.val3 <= S.val4   then case when S.val4  >= S.startvalue and S.val4  <= S.endvalue then case when S.val3 < S.val4 then '2' else '1' end  else '1' end else '0' end + 
        case when S.val4 <= S.val5   then case when S.val5  >= S.startvalue and S.val5  <= S.endvalue then case when S.val4 < S.val5 then '2' else '1' end  else '1' end else '0' end + 
        case when S.val5 <= S.val6   then case when S.val6  >= S.startvalue and S.val6  <= S.endvalue then case when S.val5 < S.val6 then '2' else '1' end  else '1' end else '0' end + 
        case when S.val6 <= S.val7   then case when S.val6  >= S.startvalue and S.val7  <= S.endvalue then case when S.val6 < S.val7 then '2' else '1' end  else '1' end else '0' end + 
        case when S.val7 <= S.val8   then case when S.val8  >= S.startvalue and S.val8  <= S.endvalue then case when S.val7 < S.val8 then '2' else '1' end  else '1' end else '0' end + 
        case when S.val8 <= S.val9   then case when S.val9  >= S.startvalue and S.val9  <= S.endvalue then case when S.val8 < S.val9 then '2' else '1' end  else '1' end else '0' end + 
        case when S.val9 <= S.val10  then case when S.val10 >= S.startvalue and S.val10 <= S.endvalue then case when S.val9 < S.val10 then '2' else '1' end  else '1' end else '0' end +
        case when S.val10 <= S.val11 then case when S.val11 >= S.startvalue and S.val11 <= S.endvalue then case when S.val10 < S.val11 then '2' else '1' end  else '1' end else '0' end +
        case when S.val11 <= S.val12 then case when S.val12 >= S.startvalue and S.val12 <= S.endvalue then case when S.val11 < S.val12 then '2' else '1' end  else '1' end else '0' end  as resulttext
    from @sample_data as S) result

Этот случай будет преобразовывать каждый переход к:

  • '0' - значение valN больше чем valN + 1
  • '1', если значение соответствует ограничениям, но valN равно valN + 1
  • и '2', если переход от valN к vanN + 1 соответствует всем вашим условия

Чем нужно работать со строкой результата. Раскомментируйте result.resulttext, если вы хотите взглянуть на «преобразованную» строку результата.

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