Мне нужно провести некоторый анализ данных в таблице с 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
Я не вижу, как это сделать с помощью одной функции ранга. Есть ли лучший, более эффективный способ?