#sql #pyspark
Вопрос:
Есть ли более простой способ использовать функции окна первого и последнего значения, чем выводить первое и последнее значения из CTE/таблиц/подзапросов, а затем объединять по ключу?
Пример игрушки ниже. На самом деле мой набор данных велик и находится в hadoop с большим количеством записей и полей.
Для каждого клиента я хочу видеть, какой первый товар они купили (указывается приращением числа покупок), а также последний товар_оригина.
«source_table» в приведенном ниже примере запроса.
идентификатор пользователя | номер покупки | пункт | item_origin |
---|---|---|---|
0001 | 1 | мяч | Огайо |
0001 | 2 | бумага | Техас |
0001 | 3 | ручка | Канзас |
0002 | 1 | ручка | Канзас |
0003 | 1 | бумага | Техас |
0004 | 2 | фрисби | Флорида |
Если бы это была полная таблица, результат должен быть:
идентификатор пользователя | first_item | last_item_оригин |
---|---|---|
0001 | мяч | Канзас |
0002 | ручка | Канзас |
0003 | бумага | Флорида |
Вот как я сейчас это реализую, но это кажется немного надуманным.
WITH min_max AS (
SELECT
customer_id,
MIN(purchase_number) AS min_row,
MAX(purchase_number) AS max_row
FROM
source_table
GROUP BY
customer_id
),
min_ AS (
SELECT
a.*
FROM
source_table a
JOIN min_max b
ON a.customer_id = b.customer_id
AND a.purchase_number = b.min_row
),
max_ AS (
SELECT
a.*
FROM
source_table a
JOIN min_max b
ON a.customer_id = b.customer_id
AND a.purchase_number = b.max_row
)
SELECT
a.customer_id,
a.item,
b.item_origin
FROM
min_ a
JOIN max_ b
ON a.customer_id = b.customer_id
Ответ №1:
Просто используйте условную агрегацию и оконные функции:
select customer_id,
max(case when seqnum = 1 then item end) as first_item,
max(case when seqnum_desc = 1 then item_origin end) as last_item_origin
from (select s.*,
row_number() over (partition by customer_id order by purchase_number) as seqnum,
row_number() over (partition by customer_id order by purchase_number desc) as seqnum_desc
from source_table s
) s
group by customer_id;