想象一下下面的场景,其中我们有两个表。 一个表存储了我们的玩家的状态,创建日期和ID,另一个表保留了他们的登录活动。
我想检索所有在 N 年前登录的玩家或从未登录的玩家。如您所见,我们有一个ID = 4的玩家从未登录过游戏因此我们也想通过检查他的创建日期将他包括在我们的列表中。
在活动表中也可能有一个玩家的多个条目,因此我们的兴趣是只带[max(LoginDate)< N >]的玩家。
我已经有一个解决方案,但是我渴望看到不同的方法。
PLAYER_TABLE
--------------------------------------
|PlayerId |CreationDate | Status |
--------------------------------------
|1 |01.01.2000 | ACTIVE |
--------------------------------------
|2 |01.01.2019 | ACTIVE |
--------------------------------------
|3 |01.01.2001 | SUSPENDED|
--------------------------------------
|4 |01.01.2004 | ACTIVE |
--------------------------------------
ACTIVITY_TABLE
-----------------------
|AccountId |LoginDate |
-----------------------
|1 |01.01.2005 |
-----------------------
|1 |05.06.2007 |
-----------------------
|2 |03.05.2010 |
-----------------------
|3 |01.01.2018 |
-----------------------
答案 0 :(得分:2)
使用CTE(公用表表达式)实现分析,并让我们根据单个日期进行过滤:
WITH CTE AS(
SELECT player.PlayerId
, activity.ddt
, coalesce(max(Activity.Logindate) over (partition by Activity.AccountID), player.CreationDate) as LastLoginOrCreation
FROM PLAYER_TABLE player
LEFT JOIN ACTIVITY_TABLE activity
ON activity.AccountId = player.PlayerId)
SELECT *
FROM CTE
WHERE player.status != 'SUSPENDED'
and LastLoginOrCreation <= to_date('2015-01-01', 'yyyy-MM-dd')
避免CTE取消内联选择,但仍然必须在两个日期进行过滤。
SELECT player.PlayerId
, activity.ddt
, coalesce(max(Activity.Logindate) over (partition by Activity.AccountID), player.CreationDate) as LastLoginOrCreation
FROM PLAYER_TABLE player
LEFT JOIN ACTIVITY_TABLE activity
ON activity.AccountId = player.PlayerId
WHERE (player.CREATION_DATE <= to_date('2015-01-01', 'yyyy-MM-dd')
OR activity.LoginDate <= to_date('2015-01-01', 'yyyy-MM-dd'))
AND player.status != 'SUSPENDED';