如何使用SQL确定事务日期的成员资格



我在一个DB中有两个非常大的表。

一个是关于会员资格和用户何时成为会员:

User|Date|Membership
1111|2020-12-01 06:00:00|False
1111|2020-12-20 18:00:00|True
1111|2020-12-30 12:00:00|False
2222|2020-12-01 06:00:00|True
2222|2020-12-20 18:00:00|False
2222|2020-12-30 12:00:00|True
...

另一个是关于这些用户的交易:

User|Date|Transaction
1111|2020-12-02 06:00:00|3.00
1111|2020-12-19 18:00:00|2.00
1111|2020-12-29 12:00:00|4.00
2222|2020-12-02 06:00:00|1.00
2222|2020-12-19 18:00:00|2.00
2222|2021-01-06 12:00:00|4.00
...

我想确定用户在使用后一个表中的新字段进行交易时是否是成员,在这种情况下,该字段如下:

User|Date|Transaction|Was_Member
1111|2020-12-02 06:00:00|3.00|False
1111|2020-12-19 18:00:00|2.00|False
1111|2020-12-29 12:00:00|4.00|True
2222|2020-12-02 06:00:00|1.00|True
2222|2020-12-19 18:00:00|2.00|True
2222|2021-01-06 12:00:00|4.00|True
...

如何在SQL中高效地执行这样的操作,将时间范围缝合在一起以检测成员身份?任何SQL语言都可以,只需要了解方法即可。

您可以根据日期(小于(连接两个表,并使用以下分析函数查找最新记录:

select user, date, transaction, membership as was_member from
(select t.user, t.date, t.transaction, m.membership,
row_number() over (partition by t.user, t.date order by m.date desc) as rn
from membership m join transactions t
on t.user = m.user and t.date >= m.date) t
where rn = 1
SELECT *,
Was_member =
(SELECT TOP 1 membership
FROM membership m
WHERE m.user = t.user
AND t.date <= m.date)
FROM transaction t;

这需要良好的索引和小事务集才能正常工作。

这也可以通过行号解决方案来实现,该解决方案对于大集合或坏索引可能更具性能。

您可能会发现left join:最简单

select t.*, m.was_member
from transactions t join
(select m.*, lead(date) over (partition by user order by date) as next_date
from members m
) m
on t.user = m.user and
t.date >= m.date and
(t.date < m.next_date or m.next_date is null);

为了提高性能,您需要members(user, date)上的索引。

可能有更有效的方法,这取决于你所说的";非常大的桌子";,数据的结构以及您使用的数据库。

相关内容

  • 没有找到相关文章

最新更新