2014-11-25 81 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