[英]How to generate all the possible combinations of exchange rates in SQL
Given a table of tuples of currency and exchange rate, such as the following: 给出货币和汇率元组的表格,如下所示:
EUR CHF 1.20
USD EUR 0.80
CHF JPY 1.30
How can I simply generate all the exchange rate between currency (A,B) and also (B,A)? 如何简单地生成货币(A,B)和(B,A)之间的所有汇率?
I would like to have the following: 我想要以下内容:
EUR CHF
CHF EUR
EUR USD
USD EUR
USD CHF
CHF USD
with all the possible combinations, ie a rate can be derived from multiple rates by chaining them 具有所有可能的组合,即通过链接它们可以从多个速率导出速率
A to B * B to C * C to D = A to D
The only way I can find to do this is using a LOOP, All my queries below use this sample data: 我能找到的唯一方法就是使用LOOP,我下面的所有查询都使用这个示例数据:
DECLARE @T TABLE (FromCurrency VARCHAR(3), ToCurrency VARCHAR(3), ExchangeRate DECIMAL(10, 5));
INSERT @T VALUES
('EUR', 'CHF', 1.20),
('USD', 'EUR', 0.80),
('CHF', 'JPY', 1.30);
The first step is to get all the reciprocal exchange rates (ie B -> A from the table of A -> B) as these are the easiest to get: 第一步是获得所有互惠汇率(即A - > B表中的B - > A),因为这些是最容易获得的:
DECLARE @TempExchangeRates TABLE (FromCurrency VARCHAR(3), ToCurrency VARCHAR(3), ExchangeRate DECIMAL(10, 5));
INSERT @TempExchangeRates (FromCurrency, ToCurrency, ExchangeRate)
SELECT FromCurrency, ToCurrency, ExchangeRate
FROM @T
UNION
SELECT ToCurrency, FromCurrency, CAST(1 / ExchangeRate AS DECIMAL(10, 5))
FROM @T t
WHERE NOT EXISTS
( SELECT 1
FROM @T t2
WHERE t.FromCurrency = t2.ToCurrency
AND t.ToCurrency = t2.FromCurrency
)
At this point we have: 此时我们有:
CHF EUR 0.83333
CHF JPY 1.30000
EUR CHF 1.20000
EUR USD 1.25000
JPY CHF 0.76923
USD EUR 0.80000
So we are still missing 所以我们仍然缺席
CHF --> USD
EUR --> JPY
JPY --> CHF
JPY --> EUR
USD --> EUR
You need to keep performing this join 您需要继续执行此连接
SELECT a.FromCurrency, b.ToCurrency, CAST(a.ExchangeRate * b.ExchangeRate AS DECIMAL(10, 5))
FROM @TempExchangeRates a
INNER JOIN @TempExchangeRates b
ON a.ToCurrency = b.FromCurrency
AND a.FromCurrency != b.ToCurrency
WHERE NOT EXISTS
( SELECT 1
FROM @TempExchangeRates c
WHERE a.FromCurrency = c.FromCurrency
AND b.ToCurrency = c.ToCurrency
)
And inserting the results until all combinations have been found: 并插入结果直到找到所有组合:
WHILE (1 = 1)
BEGIN
INSERT @TempExchangeRates (FromCurrency, ToCurrency, ExchangeRate)
SELECT DISTINCT a.FromCurrency, b.ToCurrency, CAST(a.ExchangeRate * b.ExchangeRate AS DECIMAL(10, 5))
FROM @TempExchangeRates a
INNER JOIN @TempExchangeRates b
ON a.ToCurrency = b.FromCurrency
AND a.FromCurrency != b.ToCurrency
WHERE NOT EXISTS
( SELECT 1
FROM @TempExchangeRates c
WHERE a.FromCurrency = c.FromCurrency
AND b.ToCurrency = c.ToCurrency
)
IF @@ROWCOUNT = 0
BEGIN
BREAK;
END
END
On the first loop this will retrieve 在第一个循环中,这将检索
CHF USD 1.04166
EUR JPY 1.56000
JPY EUR 0.64102
USD CHF 0.96000
Then on the second 然后在第二个
JPY USD 0.80128
USD JPY 1.24800
Then all 12 tuples will have been found. 然后将找到所有12个元组。
You can do this with a Recursive Common Table Expression 您可以使用递归公用表表达式执行此操作
Setup: 设定:
Create Table ExchangeRates (
FromCurrency char(3),
ToCurrency char(3),
Rate decimal(10, 2),
Constraint PK_ExchangeRates Primary Key (FromCurrency, ToCurrency)
);
Create Index IX_ToCurrency On ExchangeRates(ToCurrency, FromCurrency, Rate);
Insert Into ExchangeRates (FromCurrency, ToCurrency, Rate) Values
('EUR', 'CHF', 1.20),
('USD', 'EUR', 0.80),
('CHF', 'JPY', 1.30);
The CTE, which assumes all currency codes are exactly three characters: 假设所有货币代码的CTE正好是三个字符:
With AllExchanges as (
Select
FromCurrency,
ToCurrency,
Rate
From
ExchangeRates
Union
Select
ToCurrency,
FromCurrency,
Cast(1.0 / Rate As Decimal(10, 2))
From
ExchangeRates
)
, Paths as (
Select
FromCurrency,
cast(FromCurrency as varchar(max)) As ExchangePath,
ToCurrency,
Rate
From
AllExchanges a
Union All
Select
p.FromCurrency,
p.ExchangePath + ',' + p.ToCurrency,
a.ToCurrency,
Cast(p.Rate * a.Rate as Decimal(10, 2))
From
Paths p
Inner Join
AllExchanges a
On p.ToCurrency = a.FromCurrency
Where
p.ExchangePath Not Like '%' + a.ToCurrency + '%'
)
Select
FromCurrency,
ExchangePath + ',' + ToCurrency As ExchangePath,
ToCurrency,
Rate
From
Paths
http://sqlfiddle.com/#!3/0fdc5 http://sqlfiddle.com/#!3/0fdc5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.