这可能看似简单,但不知何故不是。我有一个名为TBL_A的历史汇率数据表,如下所示:
| id | rate | added_date |
|--------|--------|--------------|
| bill | 7.50 | 1/24/2011 |
| joe | 8.50 | 5/3/2011 |
| ted | 8.50 | 4/17/2011 |
| bill | 9.00 | 9/29/2011 |
在TBL_B中,我有几个小时需要加入一行TBL_A才能获得成本信息:
| id | hours | added_date |
|--------|---------|--------------|
| bill | 10 | 2/26/2011 |
| ted | 4 | 7/4/2011 |
| bill | 9 | 10/14/2011 |
正如您所看到的,对于Bill,TBL_A中有两种费率,但它们具有不同的日期。要在一段时间内正确获取Bill的成本,您必须在TBL_A中连续加入TBL_B的每一行,该行适用于该日期。
我认为这很容易;因为这不需要特别快的查询,我可以为每行成本信息做一个单独的子查询。但是,连接的子查询显然无法“看到”它们所连接的其他表。此查询会在子查询中具有“h”别名的任何内容上抛出无效标识符(ORA-00904):
SELECT h.id, r.rate * h.hours as "COST", h.added_date
FROM TBL_B h
JOIN (SELECT * FROM (
SELECT i.id, i.rate
FROM TBL_A i
WHERE i.id = h.id and i.added_date < h.added_date
ORDER BY i.added_date DESC)
WHERE rownum = 1) r
ON h.id = r.id
如果问题只是范围界定,我不知道我采取的方法是否可行。但我想在这里做的就是根据一些标准得到一行,所以我肯定对其他方法持开放态度。
编辑:所需的输出将是:
| id | cost | added_date |
|--------|---------|--------------|
| bill | 75 | 2/26/2011 |
| ted | 34 | 7/4/2011 |
| bill | 81 | 10/14/2011 |
请注意,Bill在表格的两个条目中有两种不同的费率。第一行是10 * 7.50 = 75,第二行是9 * 9.00 = 81。
答案 0 :(得分:4)
尝试使用not exists
:
select
b.id,
a.rate,
b.hours,
a.rate*b.hours as "COST",
b.added_date,
a.added_date
from
tbl_b b
inner join tbl_a a on
b.id = a.id
where
a.added_date < b.added_date
and not exists (
select
1
from
tbl_a a2
where
a2.added_date > a.added_date
and a2.added_date < b.added_date
and a2.id = a.id
)
作为解释原因发生的原因:只有相关的子查询知道它们正在运行的上下文,因为它们是针对每一行运行的。连接子查询实际上是在连接之前执行的,因此它不了解周围的表。您需要返回所有标识信息,以便在查询的顶层进行连接,而不是尝试在子查询中执行此操作。
答案 1 :(得分:1)
select id, cost, added_date from (
select
h.id,
r.rate * h.hours as "COST",
h.added_date,
-- For each record, assign r=1 for 'newest' rate
row_number() over (partition by h.id, h.added_date order by r.added_date desc) r
from
tbl_b h,
tbl_a r
where
r.id = h.id and
-- Date of rate must be entered before
-- hours billed:
r.added_date < h.added_date
)
where r = 1
;