Вычисление последовательного диапазона дат со значением в Hive

Я хочу знать, возможно ли рассчитать последовательные диапазоны определенного значения для группы идентификаторов и вернуть вычисленные значения для каждого из них. Учитывая следующие данные:

+----+----------+--------+
| ID | DATE_KEY | CREDIT |
+----+----------+--------+
|  1 |     8091 |    0.9 |
|  1 |     8092 |     20 |
|  1 |     8095 |   0.22 |
|  1 |     8096 |   0.23 |
|  1 |     8098 |   0.23 |
|  2 |     8095 |     12 |
|  2 |     8096 |     18 |
|  2 |     8097 |      3 |
|  2 |     8098 |   0.25 |
+----+----------+--------+

Я хочу следующий вывод:

+----+-------------------------------+
| ID | RANGE_DAYS_CREDIT_LESS_THAN_1 |
+----+-------------------------------+
|  1 |                             1 |
|  1 |                             2 |
|  1 |                             1 |
|  2 |                             1 |
+----+-------------------------------+

В этом случае диапазоны - это последовательные дни с кредитом меньше 1. Если между столбцом date_key есть разрыв, диапазон не должен принимать следующее значение, как в ID 1 между 8096 и 8098 ключом даты. Возможно ли это сделать с помощью оконных функций в Hive?

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

1 ответ

Вы можете сделать это с помощью промежуточной суммы, которая классифицирует строки по группам, увеличивая их на 1 каждый раз, когда обнаруживается строка с кредитом<1 (в порядке даты_ключа). После этого это просто group by,

select id,count(*) as range_days_credit_lt_1
from (select t.*
      ,sum(case when credit<1 then 0 else 1 end) over(partition by id order by date_key) as grp
      from tbl t
     ) t
where credit<1
group by id

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

with t_test as 
(
select num,row_number()over(order by num) as rn
from
(
select explode(array(1,3,4,5,6,9,10,15)) as num
)
)
select length(sign)+1 from
(
select explode(continue_sign) as sign
from 
(
select split(concat_ws('',collect_list(if(d>1,'v',d))), 'v') as continue_sign
from 
(
select t0.num-t1.num as d from t_test t0 
join t_test t1 on t0.rn=t1.rn+1
)
)
)
  1. Получить предыдущее число b в последовательности для каждого оригинала a;
  2. Проверить, есть ли ab == 1, который показывает, есть ли "пробел", отмеченный как 'v';
  3. Объедините все ab в строку, а затем разделите с помощью 'v' и вычислите длину.

Чтобы получить столбец идентификатора, следует рассмотреть другую строку, которая кодирует идентификатор.

Другие вопросы по тегам