【发布时间】:2017-08-18 05:36:00
【问题描述】:
我在我们的生产数据库中遇到了这个问题,并花了一些时间使用新创建的表重新创建它。我意识到这些查询可以用不同的方式编写,但我只是想弄清楚为什么这种方式特别不起作用,因为这种代码在我们的生产数据库中到处都是。
这是我的创建/插入:
create table Testing
(
Code varchar2(50),
EffTerm varchar2(50),
Value varchar2(50)
);
create table Testing2
(
Code varchar2(50),
Term varchar2(50)
);
insert into Testing
values('CA',100,1);
insert into Testing
values('CA',200,2);
insert into Testing
values('CB',100,3);
insert into Testing
values('CC',100,4);
insert into Testing2
values('CA',300);
insert into Testing2
values('CB',300);
insert into Testing2
values('CC',300);
这个想法是我试图获取每个“代码”的最新行。表Testing2 是具有这些任意代码当前历史的表。为了获取该代码的最新“值”,我需要获取最新的有效术语(此处表示为 100,200,300)。
与我的生产数据库中的原始问题最相似的查询如下所示:
select distinct VALUE
from Testing2
join Testing on Testing2.Code = Testing.Code
where Testing2.Term = 300
and Testing.EFFTERM = (select A.EFFTERM from
(select T.EFFTERM,
rank() over(order by T.EFFTERM desc) rowRank
from Testing T
where T.CODE = Testing.CODE
and T.EFFTERM <= Testing2.Term) A
where rowRank = 1)
order by 1;
此示例的当前项是 300(Testing2 表中的值)。为了获得有效术语,它使用窗口函数对术语进行降序排列,并通过将其包装在 select 语句中来选择最大的术语。运行这个特定的代码会给我一个输出:
Value
1
2
3
4
我的预期输出是:
Value
2
3
4
如果我所做的只是从最外层的查询中删除 distinct,它会给我我预期的输出。
经过更多测试,我认为这与窗口函数有关,并且相关子查询是一个额外的级别。
例如:
这段代码运行良好
select distinct VALUE
from Testing2
join Testing on Testing2.Code = Testing.Code
where Testing2.Term = 300
and Testing.EFFTERM = (select distinct max(T.EFFTERM) over() EFFTERM
from Testing T
where T.CODE = Testing.CODE
and T.EFFTERM <= Testing2.Term)
order by 1;
但第二次我将子查询包装在另一个选择中,如下所示:
select distinct VALUE
from Testing2
join Testing on Testing2.Code = Testing.Code
where Testing2.Term = 300
and Testing.EFFTERM = (select A.effterm from
(select distinct max(T.EFFTERM) over() EFFTERM
from Testing T
where T.CODE = Testing.CODE
and T.EFFTERM <= Testing2.Term) A)
order by 1;
又回到给我 1,2,3,4 的输出。 当然,如果我所做的只是从最外面的查询中删除 distinct,它就可以正常工作。
编辑:以防万一,我正在运行 Oracle 12c
【问题讨论】:
-
那么,testing2 总是只有有最新/有效的?
-
嗯..手头上没有播放时间 Oracle DB,但我无法在 SQL Server 中重新创建它。它不应该有什么不同,所以这很奇怪。
-
@scisimon 我使用的数据是大学的课程。 testing2 就像表中说的课程是为 Code = 'CA' in term ='300' 创建的。我需要的数据在带有通用课程信息的表中(比如它属于哪个大学)。这是名为“测试”的表。该数据是有效日期的,因为他们不想在创建的每个部分都存储所有这些信息。