Oracle中WHERE条件移入内联视图后统计计数结果不一致问题
这是符合预期的行为,两次查询的执行逻辑存在本质差异,具体原因如下:
两次查询的逻辑差异
初始查询的执行顺序:
- 读取
TBL_ID全表数据,为每个ID的所有记录按registered_date_time倒序排序,生成行号LATEST_DATE,每个ID最新的记录行号为1 - 筛选出所有行号为1的记录,再判断这些记录是否满足
ID_STATUS = 'Active'、UPPER(PROFILE_RULE) IN ('Allow 1','Allow 2')的条件,符合要求的记录才会被计数
这个逻辑的本质是:判断每个ID的最新一条记录是否符合过滤规则,符合才计入统计。
- 读取
修改后查询的执行顺序:
- 先读取
TBL_ID全表数据,过滤出满足ID_STATUS = 'Active'、UPPER(PROFILE_RULE) IN ('Allow 1','Allow 2')的所有记录 - 在过滤后的数据集里,为每个ID的剩余记录按
registered_date_time倒序排序,生成行号LATEST_DATE,取行号为1的记录计数
这个逻辑的本质是:找到每个ID所有符合过滤规则的记录里最新的那一条,只要存在符合规则的记录就会计入统计。
- 先读取
差异示例
举个简单的样本数据就能直观看出差异:
| ID | registered_date_time | ID_STATUS | PROFILE_RULE |
|---|---|---|---|
| 1 | 2024-01-02 | Inactive | Allow 1 |
| 1 | 2024-01-01 | Active | Allow 1 |
初始查询中,ID=1的最新记录是2024-01-02的非活跃记录,会被外层过滤排除,不计入统计;修改后的查询会先过滤掉非活跃记录,仅保留2024-01-01的活跃记录,这条记录行号为1,会被计入统计,最终两个查询计数结果不同。
认知偏差说明
你的认知偏差在于忽略了窗口函数的计算范围是它所在的查询块的数据集。过滤条件放在窗口函数所在的内联视图内部,会先裁剪数据集再计算窗口函数;放在外层则是先计算全量数据的窗口函数,再过滤结果,二者的计算基础完全不同,结果自然会有差异。
内容的提问来源于stack exchange,提问作者curious_nustian
相关产品推荐
相关产品推荐

