我有两个表,t1 和 t2,具有相同的列布局:client_id、transaction_date、price、product。第一个表包含主要产品,第二个表包含其他产品。我想检查是否向购买主要产品的同一客户追加销售其他产品(并检查价格)。我假设当主产品交易给同一客户之前或之后 10 天内额外销售产品时,就会发生追加销售。
t1:
client_id | 交易日期 | 价格 | 产品 |
---|---|---|---|
445 | 2024年3月1日 | 100 | 主要 |
445 | 2024年4月1日 | 100 | 主要 |
445 | 2024年4月2日 | 100 | 主要 |
339 | 2024年4月5日 | 100 | 主要 |
339 | 2024年4月6日 | 100 | 主要 |
t2:
client_id | 交易日期 | 价格 | 产品 |
---|---|---|---|
445 | 2024年4月5日 | 40 | 额外 |
339 | 2024年4月5日 | 40 | 额外 |
339 | 2024年4月6日 | 40 | 额外 |
想要:
client_id | 交易日期 | 价格 | 产品 | xsell_price |
---|---|---|---|---|
445 | 2024年3月1日 | 100 | 主要 | 空 |
445 | 2024年4月1日 | 100 | 主要 | 40 |
445 | 2024年4月2日 | 100 | 主要 | 空 |
339 | 2024年4月5日 | 100 | 主要 | 80 |
339 | 2024年4月6日 | 100 | 主要 | 空 |
我有两个无法解决的主要问题:
我希望附加产品仅分配给最旧或最新的匹配交易,以避免重复计算。例如,如果 client_id = 445 在 01.03.2024、01.04.2024 和 02.04.2024 购买了主要产品,然后在 05.04.2024 购买了附加产品,我希望附加产品的价格仅添加到该交易于 2024 年 4 月 1 日进行。 (不包括 2024 年 3 月 1 日,因为它已经超过 10 天)。
额外的产品可以多次购买,这会产生重复。例如,client_id = 339 在 01.04.2024、02.04.2024 购买了主产品,然后在 05.04.2024 和 06.04.2024 购买了附加产品,在这种情况下,这两个主要交易将重复。与第一点类似,我希望附加产品的总和仅添加到最旧或最新的主要交易中。
我尝试了这段代码,对于第一点似乎没问题,但它没有解决第二点的重复问题。
with tmp as (select t1.*,
t2.price as xsell_price, t2.transaction_date as transaction_date_xsell
from t1
left join t2 on t1.client_id = t2.client_id and t2.transaction_date between (t1.transaction_date - 5) and (t1.transaction_date + 5)),
tmp2 as (select t1.*,
row_number() over (partition by client_id, transaction_date_xsell order by transaction_date_xsell desc) as row_num
from tmp)
select t1.*,
case when row_num = 1 then xsell_price end as xsell_price_calc
from tmp2;
一种选择是使用 Over() 子句的 Partition By 和 Order By 部分中的 case 表达式来定义左连接表的 ROW_NUMBER。然后使用条件聚合ang group by:
WITH -- S a m p l e D a t a :
t1 (CLIENT_ID, TRANSACTION_DATE, PRICE, PRODUCT) AS
( Select 445, To_Date('01.03.2024', 'dd.mm.yyyy'), 100, 'main' From Dual Union All
Select 445, To_Date('01.04.2024', 'dd.mm.yyyy'), 100, 'main' From Dual Union All
Select 445, To_Date('02.04.2024', 'dd.mm.yyyy'), 100, 'main' From Dual Union All
Select 339, To_Date('05.04.2024', 'dd.mm.yyyy'), 100, 'main' From Dual Union All
Select 339, To_Date('06.04.2024', 'dd.mm.yyyy'), 100, 'main' From Dual
),
t2 (CLIENT_ID, TRANSACTION_DATE, PRICE, PRODUCT) AS
( Select 445, To_Date('05.04.2024', 'dd.mm.yyyy'), 40, 'additional' From Dual Union All
Select 339, To_Date('05.04.2024', 'dd.mm.yyyy'), 40, 'additional' From Dual Union All
Select 339, To_Date('06.04.2024', 'dd.mm.yyyy'), 40, 'additional' From Dual
)
-- M a i n S Q L :
SELECT CLIENT_ID, TRANSACTION_DATE, PRICE, PRODUCT,
Sum(Case When RN = 1 Then XSELL_PRICE End) "XSELL_PRICE"
FROM ( Select t1.CLIENT_ID, t1.TRANSACTION_DATE, t1.PRICE, t1.PRODUCT,
t2.PRICE "XSELL_PRICE",
Row_Number() Over(Partition By Case When t2.PRICE Is Not Null Then t1.CLIENT_ID Else 0 End, t2.TRANSACTION_DATE
Order By Case When t2.PRICE Is Not Null Then t1.TRANSACTION_DATE End, t2.TRANSACTION_DATE ) "RN"
From t1
Left Join t2 ON(t2.CLIENT_ID = t1.CLIENT_ID And t2.TRANSACTION_DATE - t1.TRANSACTION_DATE <= 10)
)
GROUP BY CLIENT_ID, TRANSACTION_DATE, PRICE, PRODUCT
ORDER BY CLIENT_ID Desc, TRANSACTION_DATE
/* R e s u l t :
CLIENT_ID TRANSACTION_DATE PRICE PROD XSELL_PRICE
---------- ---------------- ---------- ---- -----------
445 01.03.24 100 main
445 01.04.24 100 main 40
445 02.04.24 100 main
339 05.04.24 100 main 80
339 06.04.24 100 main */