2014-11-25 54 views
2

我有一个表与汇率:加入多个表中的SQL Server

CREATE TABLE ExchangeRates 
(
    ID int IDENTITY, 
    SellingCurrency nvarchar(20), 
    BuyingCurrency nvarchar(20), 
    Rate float, 
    CONSTRAINT PK__ExchangeRates__ID PRIMARY KEY (ID) 
) 

例如,表中包含了这样的数据:

INSERT INTO ExchangeRates 
VALUES ('USD', 'RUB', 1.2), 
     ('RUB', 'EUR', 0.5), 
     ('SEK', 'RUB', 1.3) 

我需要编写一个查询应该返回即使这两种货币没有联系(使用交易所链),两种货币的汇率也是如此。

我该怎么办?

+0

有点偏离主题,但不是你的货币总是与同一基础货币(RUB)有关?如果是的话,那么你应该总是存储相对于基础货币的汇率 - 这样你总能找到交叉汇率,只用两个连接。 – Arvo 2014-11-25 11:51:32

+0

@marc_s我想过在'SellingCurrency = BuyingCurrency'上连接表本身,但问题是这个JOIN的数量并不是恒定的。 – michaeluskov 2014-11-25 11:52:00

+0

@Arvo不,这只是一个例子,实际情况可能不同。 – michaeluskov 2014-11-25 11:52:34

回答

0

这个问题是从graph theory领域的解决方案优异的舒适感(和图表数据库,例如Neo4j),但是在关系数据库中建模图并不难,而实现像BFS/DFS或Dijkstra(用于最短路径)的路径寻找算法也是可行的,并且可能是一种可行的解决方案,足够小的数据集(这是一个例子虽然考虑到这些算法的迭代性质,但我不确定它们是否可以很好地扩展(但应该很容易在CLR过程中实现该算法以获得更好的性能)。

无论如何,我喜欢图论,并发现这个问题很有趣,并寻找,并发现,一个t-sql存储过程实现Dijkstras algorithm(其他几个人)here,并调整它适应你的数据(与对表格结构进行轻微的和不必要的改动 - 我把货币放在一张单独的表格中,不必修改程序太多),并且能够正常工作(如果您熟悉Dijkstras algorithm,代码不会很难理解作品)。

您可以通过this SQL Fiddle中的示例查看实现。

从该示例中的结果运行(五个单独的执行):

| STARTNODE | ID | NAME | DISTANCE | PATH | NAMEPATH | 
|-----------|----|------|----------|-------|-------------| 
|  USD | 2 | RUB |  1.2 | 1,2 | USD,RUB | 
|-----------|----|------|----------|-------|-------------| 
|  USD | 3 | EUR |  1.7 | 1,2,3 | USD,RUB,EUR | 
|-----------|----|------|----------|-------|-------------| 
|  RUB | 3 | EUR |  0.5 | 2,3 | RUB,EUR | 
|-----------|----|------|----------|-------|-------------| 
|  SEK | 2 | RUB |  1.3 | 4,2 | SEK,RUB | 
|-----------|----|------|----------|-------|-------------| 
|  SEK | 3 | EUR |  1.8 | 4,2,3 | SEK,RUB,EUR | 

测试数据使用这些ID号为货币:

1 = USD 
2 = RUB 
3 = EUR 
4 = SEK 

信用到author of the original algorithm

在一个请注意,值得考虑的是,即使这样使用关系数据库显然是可能的,但这可能不是一个好主意;对此有更好的解决方案。

0

当你确定你能在2级修复它,你可以使用成才这样的:


select Rate 
from ExchangeRates 
where SellingCurrency = 'SEK' 
    and BuyingCurrency = 'EUR' 
UNION 
select er1.Rate*er2.Rate as Rate 
from ExchangeRates er1 
left join ExchangeRates er2 on er2.SellingCurrency = er1.BuyingCurrency 
where er1.SellingCurrency = 'SEK' 
    and er2.BuyingCurrency = 'EUR' 
+0

问题是我不确定我能修复它。 – michaeluskov 2014-11-25 12:10:07

0
if you know that 'USD'/ 'RUB'=1.2 and 'SEK'/'RUB'= 1.3 

then you can calculate that ('USD','SEK',1.2/1.3)--->('USD','SEK',0.92) 

so, if you need rate (between two currencies 'a','b') 

that does not exists in that table 

then find two rows with common currency ('a'/'c',x) and ('b','c',y) 

and do the calculation like i do. 

('a','b',x/y) 

i hope i was clear enough. 
+0

通常人们不用格式化就放置代码。看到相反的情况很奇怪:文本被格式化为代码。 :P – Andrew 2014-11-28 12:35:05