У меня есть модель ProductPurchase
, которая описывает покупку, сделанную client
.
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import String
Base = declarative_base()
class ProductPurchase(Base):
__tablename__ = "product_client"
client_id = Column(String(255))
product_id = Column(String(255))
purchased_at = Column(DateTime(timezone=True))
Что я хочу сделать, так это получить список ProductPurchase
, где у меня будет только первая покупка client
для данного product_id
.
Например:
+-----------+------------+--------------+
| client_id | product_id | purchased_at |
+-----------+------------+--------------+
| c1 | prod1 | 2020-01-01 |
+-----------+------------+--------------+
| c1 | prod1 | 2020-01-02 |
+-----------+------------+--------------+
| c2 | prod1 | 2020-01-01 |
+-----------+------------+--------------+
| c2 | prod2 | 2020-01-01 |
+-----------+------------+--------------+
Я хочу получить следующие строки:
+-----------+------------+--------------+
| client_id | product_id | purchased_at |
+-----------+------------+--------------+
| c1 | prod1 | 2020-01-01 |
+-----------+------------+--------------+
| c2 | prod1 | 2020-01-01 |
+-----------+------------+--------------+
| c2 | prod2 | 2020-01-01 |
+-----------+------------+--------------+
Обратите внимание, что пара client_id=1
и product_id=1
отсутствует для даты 2020-01-02
, потому что ее нужно отфильтровать - цель состоит в том, чтобы получить только первую покупку товара клиентом.
Как я могу попробовать это, используя sqlalchemy
?
вот код sql, поддержка sqlalchemy all over() и PArition by, а также использование cte, просто следуйте документам sqlalchemy:
;WITH cte AS (
SELECT
*
, rank() OVER (PARTITION BY p.client_id , p.product_id ORDER BY p.purchased_at ASC) rnk
FROM
product AS p
)
SELECT cte.client_id
, cte.product_id
, cte.purchased_at
FROM cte
WHERE cte.rnk = 1
в SQLAlchemy вы можете использовать groupy по client_id и product_id и брать минимум Purchase_at.
Что-то вроде этого
from sqlalchemy import func
session.query(ProductPurchase.client_id ,ProductPurchase.purchased_id , func.min(ProductPurchase.purchased_at)).group_by(ProductPurchase.client_id ,ProductPurchase.purchased_id).all()
Это просто и то, что я искал, спасибо