我有两张桌子,如下图所示。我需要在dateOfPurchase找到有效的exchangeRate。我尝试了一些相关的子查询,但是我很难在子查询中使用相关记录。
我希望解决方案需要遵循这个基本大纲:
我的表格:
purchasesTable :
> dateOfPurchase | costOfPurchase | countryOfPurchase
> 29-March-2010 | 20.00 | EUR
> 29-March-2010 | 3000 | JPN
> 30-March-2010 | 50.00 | EUR
> 30-March-2010 | 3000 | JPN
> 30-March-2010 | 2000 | JPN
> 31-March-2010 | 100.00 | EUR
> 31-March-2010 | 125.00 | EUR
> 31-March-2010 | 2000 | JPN
> 31-March-2010 | 2400 | JPN
costOfPurchase与给定countryCode的本地货币无关
exchangeRateTable
> effectiveDate | countryCode | exchangeRate
> 29-March-2010 | JPN | 90
> 29-March-2010 | EUR | 1.75
> 30-March-2010 | JPN | 92
> 31-March-2010 | JPN | 91
> dateOfPurchase | costOfPurchase | countryOfPurchase | exchangeRate
> 29-March-2010 | 20.00 | EUR | 1.75
> 29-March-2010 | 3000 | JPN | 90
> 30-March-2010 | 50.00 | EUR | 1.75
> 30-March-2010 | 3000 | JPN | 92
> 30-March-2010 | 2000 | JPN | 92
> 31-March-2010 | 100.00 | EUR | 1.75
> 31-March-2010 | 125.00 | EUR | 1.75
> 31-March-2010 | 2000 | JPN | 91
> 31-March-2010 | 2400 | JPN | 91
因此,例如在结果中,3月31日欧元的汇率为1.75。
我正在使用Access,但MySQL的答案也可以。
更新
SELECT dateOfPurchase, costOfPurchase, countryOfPurchase, exchangeRate
FROM purchasesTable p
LEFT OUTER JOIN
(SELECT e1.exchangeRate, e1.countryCode, e1.effectiveDate, min(e2.effectiveDate) AS enddate
FROM exchangeRateTable e1
LEFT OUTER JOIN
exchangeRateTable e2
ON e1.effectiveDate < e2.effectiveDate AND e1.countryCode = e2.countryCode
GROUP BY e1.exchangeRate, e1.countryCode, e1.effectiveDate) e
ON p.dateOfPurchase >= e.effectiveDate AND (p.dateOfPurchase < e.enddate OR e.enddate is null) AND p.countryOfPurchase = e.countryCode
我不得不做一些小改动。
答案 0 :(得分:3)
如果你的exchangeRate表没有任何空白,这很简单:
select dateOfPurchase, costOfPurchase, countryOfPurchase, exchangeRate
from purchasesTable p
inner join
exchangeRateTable e
on p.dateofpurchase = e.effectivedate
and p.countryofpurchase = e.countrycode
如果它确实有间隙(有效速率设置为1/1并且直到1/3才变化,因此1/1速率适用于1/2),然后它会变得更复杂,因为结束日期只是暗示。在这种情况下,以下应该有效:
select dateOfPurchase, costOfPurchase, countryOfPurchase, exchangeRate
from purchasesTable p
left outer join
(select e1.exchangeRate, e1.countrycode,
e1.effectivedate, min(e2.effectivedate) as enddate
from exchangeRateTable e1
left outer join
exchangeRateTable e2
on e1.effective_date < e2.effective_date
and e1.countrycode = e2.countrycode
group by e1.exchangeRate, e1.countrycode,
e1.effectivedate) e
on p.dateofpurchase >= e.effectivedate
and (p.dateofpurchase < e.enddate
or e.enddate is null)
and p.countryofpurchase = e.countrycode
如果您需要使用此解决方案,您可能希望将最里面的查询放在存储的查询中,以简化此操作并使结束日期可用于其他进程。
我们正在做的是从汇率表(e1
)获取每个记录并将其加入到同一表(e2
)中稍后发生的所有条目中。我们取第二组值中的最小值(min(e2.effectivedate)
)。
假设您只有三个值:
1/1/2000
1/3/2000
1/5/2000
联接将为您提供以下结果(每个值与所有更大的值组合):
1/1/2000 < 1/3/2000
1/1/2000 < 1/5/2000
1/3/2000 < 1/5/2000
1/5/2000 < [null]
由于没有1/5/2000的值小于并且我们指定了外连接,因此该行将为第二个表设置一个空值。然后我们指定我们只想要第二个表中的最小值,因此结果集减少到:
1/1/2000 < 1/3/2000
1/3/2000 < 1/5/2000
1/5/2000 < [null]
最后,在最外层的连接中,我们告诉查询加入这两个值之间的所有日期。但是,因为一个集合具有空结束日期,所以我们添加一个或条件来忽略该情况下的上限。
我开始从Litwin,et.al。的“Access 95 Developer's Handbook”学习SQL并经常阅读Usenet,所以我的资料来源已经过时......