sql: инструкции по группированию / разбиению таблицы с чередованием с нулями - PullRequest
0 голосов
/ 01 января 2019

Предположим, у меня есть две таблицы, одна из которых описывает события с какими-то временными метками, а другая описывает периоды (определяемые их временем начала), например:

create table periods (name varchar(16), start int);
insert into periods values
    ('day1', 24), ('day2', 35), ('day3', 49);

create table events (id varchar(16), ts int);
insert into events values
    ('pak', 27), ('mak', 41), ('kew', 30),
    ('sippa', 58), ('fucha', 50), ('den', 28);

В конечном итоге я хочу сопоставить события с периодами,но используя «чередующийся» подход, а не объединять.Тогда я представляю, что «чередующийся» набор будет выглядеть так:

select * from (
    (select name as per, s as x, 1 as pri, null as id from periods) 
    union all
    (select null as per, t as x, 2 as pri, id from events)
) v order by x, pri;

+------+------+-----+-------+
| per  | x    | pri | id    |
+------+------+-----+-------+
| day1 |   24 |   1 | NULL  |
| NULL |   27 |   2 | pak   |
| NULL |   28 |   2 | den   |
| NULL |   30 |   2 | kew   |
| day2 |   35 |   1 | NULL  |
| NULL |   41 |   2 | mak   |
| day3 |   49 |   1 | NULL  |
| NULL |   50 |   2 | fucha |
| NULL |   58 |   2 | sippa |
+------+------+-----+-------+

И теперь я хочу использовать select ... over ... partition by здесь, чтобы строка с ненулевым полем per и последующие строки с этим полем обнулялисьпопадаю в тот же раздел, над которым я могу использовать min(x) (или имя периода каким-либо образом).

Но я озадачен, как написать это partition by.К чему?

Заранее спасибо!

PS что касается конкретного диалекта SQL, то речь идет о hive - поэтому я пытаюсь избежать объединения - но я надеюсь, что смогуАдаптируйте подсказки с синтаксисом для других механизмов БД.


Решено - см. принятый ответ ниже.Нам нужен дополнительный вложенный запрос, в котором мы применяем COUNT к столбцу per.Это возвращает количество строк до сих пор (т.е. выше текущего), которое имеет ненулевое значение для поля.Таким образом, мы получили столбец, который имеет отдельный номер для каждой группы.Внешний запрос тогда нужно только разделить по этому столбцу.

1 Ответ

0 голосов
/ 01 января 2019

Многие базы данных поддерживают аргумент стандарта ISO / ANSI IGNORE NULL s для LAG().Это просто позволяет:

select v.*,
       lag(per ignore nulls) over (order by x) as new_per
from ((select name as per, s as x, 1 as pri, null as id from periods 
      ) union all
      (select null as per, t as x, 2 as pri, id from events
      )
     ) v
order by x, pri;

Hive не поддерживает эту опцию, но вы можете сделать то же самое с двумя уровнями оконных функций:

select v.*,
       max(per) over (partition by grp) as new_per
from (select v.*,
             count(per) over (order by x) as grp
      from ((select name as per, s as x, 1 as pri, null as id from periods 
            ) union all
            (select null as per, t as x, 2 as pri, id from events
            )
           ) v
    ) v
order by x, pri;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...