这个问题在这里已有答案:
想象一下我们有两个表的情况。一个表存储我们的玩家的状态,创建日期和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 |
-----------------------
使用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';