SQL: выбор данных до первого появления определенного значения - PullRequest
0 голосов
/ 25 ноября 2018

Например, у меня есть данные заказа от клиентов, например:

test = spark.createDataFrame([
    (0, 1, 1, "2018-06-03"),
    (1, 1, 1, "2018-06-04"),
    (2, 1, 3, "2018-06-04"),
    (3, 1, 2, "2018-06-05"),
    (4, 1, 1, "2018-06-06"),
    (5, 2, 3, "2018-06-01"),
    (6, 2, 1, "2018-06-01"),
    (7, 3, 1, "2018-06-02"),
    (8, 3, 1, "2018-06-02"),
    (9, 3, 1, "2018-06-05")
])\
  .toDF("order_id", "customer_id", "order_status", "created_at")
test.show()

enter image description here

Каждый заказ имеет свой собственный статус, 1означает вновь созданный, но не завершенный, 3 означает, что он оплачен и завершен.

Теперь я хочу провести анализ заказа, поступившего от

  • новых клиентов (которые не совершили покупкудо)
  • старых клиентов (которые уже закончили покупку)

, поэтому я хочу добавить функцию к вышеприведенным данным, превратившись в вот это

enter image description here

Логика для каждого клиента, каждый заказ, созданный до первого заказа со статусом 3 (включая себя), считается как поступивший от new customer, и каждый заказ после этогосчитается как old customer.

Или, если выразить это иначе, выбрать данные до первого вхождения значения 3 (для каждого заказа клиента, сортировать по дате asc)

Как я могу это сделать в SQL?

Я искал вокруг, но не нашел хорошего решения.Если в Python, я думаю, возможно, я просто сделаю какой-то цикл, чтобы получить значения.

Ответы [ 2 ]

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

Вы можете сделать это с помощью оконных функций в Spark:

select t.*,
       (case when created_at > min(case when status = 3 then created_at end) over (partition by customer_id)
             then 'old'
             else 'new'
        end) as customer_status
from test t;

Обратите внимание, что это назначает «новых» клиентам без заказа со статусом «3».

Вы также можете написатьэто с использованием join и group by:

select t.*,
       coalesce(t3.customer_status, 'old') as customer_status
from test t left join
     (select t.customer_id, min(created_at) as min_created_at,
             'new' as customer_status
      from t
      where status = 3
      group by t.customer_id
     ) t3
     on t.customer_id = t3.customer_id and
        t.created_at <= t3.min_created_at;
0 голосов
/ 25 ноября 2018

Это проверено на SQLite:

SELECT order_id, customer_id, order_status, created_at, 
CASE
     WHEN order_id > (SELECT MIN(order_id) FROM orders WHERE customer_id = o.customer_id AND order_status = 3) THEN 'old'
     ELSE 'new'  
END AS customer_status
FROM orders o
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...