Как найти записи с одинаковым значением в смежных записях на Sql Server?(Я считаю правильный термин для этого региона ??) - PullRequest
2 голосов
/ 08 июля 2011

Нашли время начала и окончания для смежных записей, имеющих одинаковое значение?

У меня есть таблица, которая содержит показания пульса (в ударах в минуту) и поле даты и времени. (Фактически это поля heartrate_id, heartrate и datetime.) Данные генерируются устройством, которое регистрирует частоту сердечных сокращений и время каждые 6 секунд. Иногда монитор сердечного ритма будет давать ложные показания, и записанные удары в минуту будут «зависать» в течение некоторого времени. Под палками я имею в виду, что количество ударов в минуту будет одинаковым в соседние времена.

В основном мне нужно найти все записи, в которых частота сердечных сокращений одинакова (например, 5 ударов в минуту, 100 ударов в минуту и ​​т. Д.), Но только на смежных записях. Если устройство записывает 25 ударов в минуту в течение 3 последовательных чтений (или 100 последовательных чтений), мне нужно найти эти события. Результаты должны иметь частоту сердечных сокращений, время начала сердечных сокращений и время, когда частота сердечных сокращений закончилась, и в идеале результаты должны выглядеть примерно так:

heartrate starttime endtime
--------- --------- --------
1.00      21:12:00  21:12:24
35.00     07:00:12  07:00:36

Я пробовал несколько разных подходов, но пока я вычеркиваю. Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

3 голосов
/ 09 июля 2011

EDIT:

После проверки ни одна из моих оригинальных работ по этому ответу не была очень хорошей. Это на самом деле относится к классу проблем, известных как , и в этом пересмотренном ответе будет использоваться информация, которую я почерпнул из аналогичных вопросов / выучил с тех пор, как впервые ответил на этот вопрос.

Оказывается, этот запрос можно сделать на лот проще, чем я думал:

WITH Grouped_Run AS (SELECT heartRate, dateTime,
                            ROW_NUMBER() OVER(ORDER BY dateTime) -  
                            ROW_NUMBER() OVER(PARTITION BY heartRate ORDER BY dateTime) AS groupingId
                     FROM HeartRate)

SELECT heartRate, MIN(dateTime), MAX(dateTime)
FROM Grouped_Run
GROUP BY heartRate, groupingId
HAVING COUNT(*) > 2

Демонстрация SQL Fiddle

<ч />

Так что здесь происходит? Одним из определений проблем пробелов и островков является необходимость «групп» последовательных значений (или их отсутствие). Часто последовательности создаются для решения этой проблемы, используя часто упускаемый из виду / слишком интуитивный факт: вычитание последовательностей дает постоянное значение.

Например, представьте следующие последовательности и вычитание (значения в строках не важны):

position   positionInGroup  subtraction
=========================================
1          1                0
2          2                0
3          3                0
4          1                3
5          2                3
6          1                5
7          4                3
8          5                3

position - простая последовательность, сгенерированная для всех записей.
positionInGroup - это простая последовательность, сгенерированная для каждого набора различных записей. В этом случае на самом деле есть 3 различных набора записей (начиная с position = 1, 4, 6).
subtraction является результатом разницы между двумя другими столбцами. Обратите внимание, что значения могут повторяться для разных групп!
Одно из ключевых свойств, которыми должны обладать последовательности, заключается в том, что они должны быть сгенерированы по строкам данных в том же порядке , или это нарушается.

Так как SQL делает это? Благодаря использованию ROW_NUMBER() эта функция сгенерирует последовательность чисел в «окне» записей:

ROW_NUMBER() OVER(ORDER BY dateTime)

сгенерирует последовательность position.

ROW_NUMBER() OVER(PARTITION BY heartRate ORDER BY dateTime)

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

В первоначальном ответе запрашивалось время начала и окончания каждого из «циклов» застрявших сердцебиений. Это стандарт MIN(...) / MAX(...), что означает GROUP BY. Нам нужно использовать оба исходный столбец heartRate (потому что это неагрегированный столбец) и наш сгенерированный groupingId (который идентифицирует текущий "прогон" для каждого застрявшего значения) .

Часть вопроса, задаваемая только для прогонов, которые повторяются три или более раз. HAVING COUNT(*) > 2 - это инструкция для игнорирования прогонов длиной 2 или меньше; он считает количество строк на группу.

0 голосов
/ 21 июля 2011

Я рекомендую статью Бен-Гана об интервальной упаковке, которая относится к вашей проблеме смежности.

БЛИЦ-вызов-упаковка-дата и время-интервалы

решение к упаковке, дата и время-интервалы-головоломка

...