在其他谓词之前评估分析函数上的 WHERE 谓词(Oracle 分析函数)
背景
示例数据集
#Employee
Id | Period | Status
---------------------
1 | 1 | L
1 | 2 | G
2 | 3 | L
我想要一个简单的选择查询,仅当状态=“L”时才能生成员工的最新记录(按期间)。
结果将如下所示:
#Desired Results
Id | Period | Status | Sequence
-------------------------------
2 | 3 | L | 1
幼稚的尝试
显然,我对查询的幼稚尝试不起作用:
#select query
SELECT *, RANK() OVER (PARTITION BY id ORDER BY period ASC) sequence
FROM employees
WHERE status = 'L'
AND sequence = 1
其结果如下:
#Naive (incorrect) Results
ID | Period | Status | Sequence
-------------------------------
1 | 1 | L | 1
2 | 3 | L | 1
了解在 SQL 中评估子句的顺序可以解释为什么它不起作用。以下是我的查询的评估方式:
- 隔离 status='L' 的行 对
- 行进行排名 隔离
- 排名靠前的行
我想要以下内容:
- 对行排名
- 隔离排名靠前的行
- 隔离 status='L' 的
行 问题
Is possible--只需对 SELECT/WHERE 子句进行简单修改并仅使用基本谓词运算符即可确保 WHERE 子句中基于分析函数的谓词在非聚合谓词之前得到评估?
是否还有其他可以作为最终用户在 Oracle Discoverer Plus 中实施的解决方案?
谢谢!
Background
Sample data set
#Employee
Id | Period | Status
---------------------
1 | 1 | L
1 | 2 | G
2 | 3 | L
I want a simple select query to yield employees' latest record (by period) only if the status='L'.
The results would look like this:
#Desired Results
Id | Period | Status | Sequence
-------------------------------
2 | 3 | L | 1
Naive attempt
Obviously, my naive attempt at a query does not work:
#select query
SELECT *, RANK() OVER (PARTITION BY id ORDER BY period ASC) sequence
FROM employees
WHERE status = 'L'
AND sequence = 1
Which results in the following:
#Naive (incorrect) Results
ID | Period | Status | Sequence
-------------------------------
1 | 1 | L | 1
2 | 3 | L | 1
Knowing the order that clauses are evaluated in SQL explains why it doesn't work. Here is how my query is evaluated:
- Isolate rows where status='L'
- Rank the rows
- Isolate top rank row
I want the following:
- Rank rows
- Isolate the top ranked rows
- Isolate where status='L'
Questions
Is possible--with only a simple modification to the SELECT/WHERE clauses and using only basic predicate operators--to ensure that predicates based on analytic functions in the WHERE clause get evaluated before the non-aggregate predicates?
Anyone have other solutions that can be implemented as an end-user in Oracle Discoverer Plus?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
从技术上讲,以下不是子查询,而是派生表,
我想不出针对您的问题的不同解决方案。
Technically the following is not a sub-query but a derived table
I can't think of a different solution to your problem.
经典的分组依据
存在
The classic Group by
Exists
我可能不得不做一个“多比”,然后把我的耳朵撞到烤箱门上,并为此熨烫我的手......
您可以创建一个评估当前行的函数。
请注意,这本质上是不可扩展的。但我想这总比没有好。
创建示例数据:
创建数据库中最慢的函数:
演示函数的使用:
冲向烤箱...
I'll probably have to do a "Dobby" and slam my ear in the oven door and iron my hands for this...
You can create a function which evaluates the current row.
Note that this is inherently non-scalable. But I guess it's better than nothing.
Create the sample data:
Create the slowest function in the database:
Demonstrates the use of the function:
Rushes towards the oven...
从中选择*
(SELECT a.*,rank() OVER (ORDER BY period ASC) 序列
从
(从其中选择 *
(
从双选择 1 个 ID、1 个周期、“L”状态
联合所有
从双选择 1 个 ID、2 个周期、“G”状态
联合所有
从双选择 2 个 ID、3 个周期、“L”状态
)
其中状态 = 'L'
) 一个
)
其中序列 = 1
select * from
(SELECT a.*, rank() OVER (ORDER BY period ASC) sequence
from
(select * from
(
select 1 id, 1 period, 'L' status from dual
union all
select 1 id, 2 period, 'G' status from dual
union all
select 2 id, 3 period, 'L' status from dual
)
where status = 'L'
) a
)
where sequence = 1