Как я могу пройтись по таблице SQL и выбрать всплески в данных? - PullRequest
1 голос
/ 26 мая 2020

Допустим, у меня есть следующая таблица:

Id|name|spike|timestamp
1 |John|15   |111
2 |Jim |12   |112
3 |Jeff|13   |113
4 |Joe |4    |114
5 |Jess|0    |115
6 |Jill|0    |116
7 |Jey |13   |117
8 |Joy |15   |118
9 |Jess|14   |119
10|Joe |0    |120

Мне нужно пройти по таблице и выбрать данные, где spike > 10, и разделить строки на разные наборы данных. Приемлемый запрос для верхней таблицы должен привести к:

Id|name|spike|timestamp
1 |John|15   |111
2 |Jim |12   |112
3 |Jeff|13   |113

и

Id|name|spike|timestamp
7 |Jey |13   |117
8 |Joy |15   |118
9 |Jess|14   |119

Мне нужно обработать все всплески в таблице.

Изменить: Я не знаю количество островов в таблице или расстояние между ними.

Ответы [ 3 ]

3 голосов
/ 26 мая 2020

Вы можете разделить свои данные на острова, используя CTE для вычисления строк в соответствии с меткой времени, а также разбить их на spike > 10, а затем взяв DENSE_RANK() над их разницей, чтобы вычислить номер острова. Затем вы можете выбрать один из них на основе номера island:

WITH CTE AS (
  SELECT *,
         ROW_NUMBER() OVER (ORDER BY timestamp) AS rn,
         ROW_NUMBER() OVER (PARTITION BY spike > 10 ORDER BY timestamp) AS sn
  FROM data
),
islands AS (
  SELECT id, name, spike, timestamp,
         DENSE_RANK() OVER (ORDER BY rn - sn) AS island
  FROM CTE
  WHERE spike > 10
)
SELECT *
FROM islands 
WHERE island = 2

Вывод:

id  name    spike   timestamp   island
7   Jey     13      117         2
8   Joy     15      118         2
9   Jess    14      119         2

Демо на dbfiddle

Примечание что если у вас могут быть повторяющиеся значения timestamp, но они увеличиваются с id, вам следует изменить предложения ORDER BY timestamp на ORDER BY id.

3 голосов
/ 26 мая 2020

Если у вас нет представления о количестве островов, используйте это решение подхода Dynami c. вот демонстрация .

with cte as
(
    select
        *,
        id - row_number() over (order by id) as rnk
    from myTable
    where spike > 10
),
islands as
(
  select
      *,
      (select count(distinct rnk)::int from cte) as total_islands
  from cte
),
buckets as
(
  select
    Id,
    name,
    spike,
    timestamp,
    NTILE(total_islands) Over (Order by id) as island
  from islands
)  

select *
from buckets
where island = 2

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

сначала создайте cte

with cte as
(
  select
    Id,
    name,
    spike,
    timestamp,
    NTILE(2) Over (Order by id) as nums
  from myTable
  where spike > 10
)  

Затем запустите первый запрос, чтобы получить первую часть

select  
    Id,
    name,
    spike,
    timestamp
from cte
where nums = 1;

Вывод:

| id  | name | spike | timestamp |
| --- | ---- | ----- | --------- |
| 1   | John | 15    | 111       |
| 2   | Jim  | 12    | 112       |
| 3   | Jeff | 13    | 113       |

Теперь запустите второй запрос, чтобы получить вторую часть

select  
    Id,
    name,
    spike,
    timestamp
from cte
where nums = 2;

Вывод:

| id  | name | spike | timestamp |
| --- | ---- | ----- | --------- |
| 7   | Jey  | 13    | 117       |
| 8   | Joy  | 15    | 118       |
| 9   | Jess | 14    | 119       |
0 голосов
/ 26 мая 2020

Есть много способов справиться с проблемами промежутков и островков. В этом случае совокупная сумма однозначно идентифицирует каждую группу.

select t.*
from (select t.*,
             count(*) filter (where spike <= 10) over (order by timestamp) as island
      from t
     ) t
where spike > 10;

Подсчитывается количество spike значений меньше или равных 10 . Это константа для каждой группы последовательных "острых" чисел.

Если вы хотите пронумеровать острова, просто используйте dense_rank():

select t.*, dense_rank() over (order by island) as grouping_number
from (select t.*,
             count(*) filter (where spike <= 10) over (order by timestamp) as island
      from t
     ) t
where spike > 10;

Здесь - это db <> скрипка.

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