Sql-Get время колеблется от миллиона + строк для конкретного условия - PullRequest
0 голосов
/ 31 мая 2018

Я работаю с SQL Server 2012, у меня есть таблица с приблизительно 35 столбцами и 10+ миллионами строк.Мне нужно найти временные диапазоны по всем данным, где значение какого-либо конкретного столбца совпадает, например. Пример данных как показано ниже

 Datetime        col1  col2  col3
2018-05-31 0:00     1   2   1 
2018-05-31 13:00    2   2   2
2018-05-31 14:30    3   2   1
2018-05-31 15:00    4   3   1
2018-05-31 16:00    4   5   1
2018-05-31 17:00    3   2   2
2018-05-31 17:30    3   2   4
2018-05-31 18:00    2   2   4
2018-05-31 20:00    1   2   6
2018-05-31 21:00    2   2   3
2018-05-31 21:10    2   2   1
2018-05-31 22:00    1   6   3
2018-05-31 22:00    4   5   1
2018-05-31 23:59    4   7   2

Найти временной диапазон по данным, где значение col2 = <2, соответственно мойожидаемый набор результатов следующий: </p>

Start Time           End time           Time Diff
2018-05-31 0:00     2018-05-31 14:30    14:30:00
2018-05-31 17:00    2018-05-31 21:10    4:10:00

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

  1. Порядок по дате_Время

  2. Отсканируйте строки, найдите первую строку, в которой точно совпадает значение, и запишите эту метку времени как время начала.

  3. Просканируйте дальнейшие строки, пока я не получу строку, где условие нарушается, и запомните эту метку времени как время окончания.

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

1 Ответ

0 голосов
/ 31 мая 2018

Здесь мы можем использовать слегка измененную методику определения разности номеров строк.Цель первого CTE, помеченного cte1, состоит в том, чтобы добавить вычисляемый столбец, который помечает острова, которые мы хотим, с col2 значениями <= 2 как 1, а все остальное как 0. Затем мы можем вычислить разницу двух строкчисла и агрегировать по островам, чтобы найти время начала и окончания, а также разницу между этими временами. </p>

WITH cte1 AS (
    SELECT *,
        CASE WHEN col2 <= 2 THEN 1 ELSE 0 END AS class
    FROM yourTable
),
cte2 AS (
    SELECT *,
        ROW_NUMBER() OVER (ORDER BY Datetime) -
        ROW_NUMBER() OVER (PARTITION BY class ORDER BY Datetime) rn
    FROM cte1
)

SELECT
    MIN(Datetime) AS [Start Time],
    MAX(Datetime) AS [End Time],
    CONVERT(TIME, MAX(Datetime) - MIN(Datetime)) AS [Time Diff]
FROM cte2
WHERE class = 1
GROUP BY rn
ORDER BY MIN(Datetime);

enter image description here

Демо

...