применение оконной функции к большому набору данных (как оптимизировать?) - PullRequest
0 голосов
/ 02 ноября 2018

Мне нужно провести некоторый анализ данных в таблице с 400+ миллионами строк. Я получил это, чтобы работать на небольшом образце, но я уверен, что в производстве не хватит памяти.

Структура таблицы выглядит следующим образом (для миллионов серийных номеров):

+------------+---------------+------------+----------+
|    date    | serial_number |  status_1  | status_2 |
+------------+---------------+------------+----------+
| 10/1/2018  |           123 | warehouse  | v        |
| 10/10/2018 |           123 | warehouse  | w        |
| 10/20/2018 |           123 | warehouse  | x        |
| 11/2/2018  |           123 | in transit | y        |
+------------+---------------+------------+----------+

Мне нужно получить даты, когда status_1 = «в пути» в настоящее время и status_2 = «x» в предыдущую дату. Это должно выглядеть так:

+-----------+---------------+------------+----------+------------+
|  date_1   | serial_number |  status_1  | status_2 |   date_2   |
+-----------+---------------+------------+----------+------------+
| 11/2/2018 |           123 | in transit | x        | 10/20/2018 |
+-----------+---------------+------------+----------+------------+

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

with transit as (
select 
*
from (
    select *,
    rank() over(partition by serial_number order by date desc) rnk
    from sample_t 
    order by serial_number, date asc
    ) 
where rnk=1 and status_1 = 'in transit'
),
x_type as (
select 
*
from (
    select *,
    rank() over(partition by serial_number order by date desc) rnk
    from sample_t 
    order by serial_number, date asc
    ) 
where rnk>1 and status_2 = 'x'
)
select tr.date date_1,
tr.serial_number,
tr.status_1,
x.status_2,
x.date date_2
from transit tr left join x_type x on tr.serial_number = x.serial_number

Я не вижу, как это сделать с помощью одной функции ранга. Есть ли лучший, более эффективный способ?

1 Ответ

0 голосов
/ 02 ноября 2018

Вы можете использовать lag для этого.

select *
from (select t.*
      ,lag(status_2) over(partition by serial_no order by date) as prev_status_2
      ,lag(date) over(partition by serial_no order by date) as prev_date
      from tbl t  
     ) t 
where status_1 = 'in_transit' and prev_status_2 = 'x'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...