0

次のような通貨と為替レートのタプルのテーブルが与えられます。

EUR CHF 1.20
USD EUR 0.80
CHF JPY 1.30

通貨(A、B)と(B、A)の間のすべての為替レートを簡単に生成するにはどうすればよいですか?

私は次のものが欲しいです:

EUR CHF
CHF EUR

EUR USD
USD EUR

USD CHF
CHF USD

可能なすべての組み合わせで、つまり、レートはそれらを連鎖させることによって複数のレートから導き出すことができます

A to B * B to C * C to D = A to D
4

2 に答える 2

1

これを行うために私が見つけることができる唯一の方法は、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);

最初のステップは、すべての相互為替レート(つまり、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
        )

この時点で、次のようになります。

CHF EUR 0.83333
CHF JPY 1.30000
EUR CHF 1.20000
EUR USD 1.25000
JPY CHF 0.76923
USD EUR 0.80000

だから私たちはまだ行方不明です

CHF --> USD 
EUR --> JPY 
JPY --> CHF 
JPY --> EUR 
USD --> EUR 

この結合を実行し続ける必要があります

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
        )

そして、すべての組み合わせが見つかるまで結果を挿入します。

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

最初のループでこれは取得します

CHF USD 1.04166
EUR JPY 1.56000
JPY EUR 0.64102
USD CHF 0.96000

次に2番目に

JPY USD 0.80128
USD JPY 1.24800

その後、12個のタプルがすべて検出されます。

于 2012-12-06T12:36:53.263 に答える
1

これは、再帰共通テーブル式を使用して実行できます

設定:

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);

すべての通貨コードが正確に3文字であると想定する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

于 2012-12-06T14:41:57.527 に答える