样本数据集
#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中评估子句的顺序解释了为什么它不起作用。以下是我的查询评估方式:
我想要以下内容:
是否可以 - 只对SELECT / WHERE子句进行简单修改并仅使用基本谓词运算符 - 以确保在非聚合谓词之前评估基于WHERE子句中的分析函数的谓词?
任何人都可以在Oracle Discoverer Plus中作为最终用户实施其他解决方案吗?
谢谢!
答案 0 :(得分:3)
是否可以在没有子查询的情况下执行此操作
从技术上讲,以下不是子查询,而是派生表
SELECT *
FROM (
SELECT *,
RANK() OVER (PARTITION BY id ORDER BY period ASC) sequence
FROM employees
) t
WHERE status = 'L'
AND sequence = 1
我想不出你问题的不同解决方案。
答案 1 :(得分:0)
经典集团
SELECT e.id, e.period, e.status, 1 sequence
FROM
(
SELECT id, min(period) period
FROM employees
GROUP BY id
) X
JOIN employees e on e.period=X.period and e.id=X.id
WHERE e.status = 'L'
已存在
select e.id, e.period, e.status, 1 sequence
FROM employees e
WHERE e.status = 'L'
AND NOT EXISTS (select *
from employees e2
where e2.id=e.id and e2.period>e.period)
答案 2 :(得分:0)
我可能不得不做一个“Dobby”,然后把我的耳朵塞进烤箱门,然后熨烫我的手......
您可以创建一个评估当前行的函数 请注意,这本质上是不可扩展的。但我想这比没有好。
创建样本数据:
--drop table employee purge;
create table employee(
id number not null
,period number not null
,status char(1) not null
,constraint employee_pk primary key(id, period)
);
insert into employee(id,period, status) values(1, 1, 'L');
insert into employee(id,period, status) values(1, 2, 'G');
insert into employee(id,period, status) values(2, 3, 'L');
commit;
在数据库中创建最慢的函数:
create or replace function i_am_slow(
ip_id employee.id%type
,ip_period employee.period%type
)
return varchar2
as
l_count number := 0;
begin
select count(*)
into l_count
from employee e
where e.id = ip_id
and e.period = ip_period
and e.status = 'L'
and not exists(
select 'x'
from employee e2
where e2.id = e.id
and e2.period > e.period);
if l_count = 1 then
return 'Y';
end if;
return 'N';
end;
/
演示使用该功能:
select id, period, status
from employee
where i_am_slow(id, period) = 'Y';
ID PERIOD STATUS
---------- ---------- ------
2 3 L
冲向烤箱......