简体   繁体   English

如何为以下业务逻辑编写 sql 查询?

[英]How to write a sql query for following business logic?

I have three following three tables,我有三个以下三个表,

1. ItemProdCodeValueMapping (ItemId and ProdCd are part of primary key) 1. ItemProdCodeValueMapping (ItemId 和 ProdCd 是主键的一部分)

ItemId    ProdCd    ProdValue    ProdCurrencyCd
123       Shampoo   4.6          GBP           
124       Shampoo   5.8          GBP           
128       Shampoo   7.8          AUD           
125       Cashews   7.6          CAD           
125       ESwitch   17.6         CAD           
123       ESwitch   13.80        USD           

2. ItemDetails (ItemId is primary key) 2.ItemDetails (ItemId为主键)

ItemId    OrderDate
123       2019-04-15
124       2017-07-15
125       2016-05-25

3. ExchangeRates (This table has exchange rates with respect to USD, meaning exchange rates only in term of USD to other currencies) 3. ExchangeRates (此表有相对于美元的汇率,表示仅以美元对其他货币的汇率)

SourceCurrency    TargetCurrency    ExchangeDate    ExchangeRate
USD               GBP               2017-01-23        0.8039  
USD               GBP               2017-01-24        0.8034
USD               GBP               2017-01-25        0.7942
USD               CAD               2017-01-23        1.10
USD               CAD               2017-01-24        1.12
USD               CAD               2017-01-25        1.18
USD               AUD               2017-01-23        1.10
USD               AUD               2017-01-24        1.12
USD               AUD               2017-01-25        1.18`

QUERY Expectation My client is providing me a prodCd and currency code eg ( Shampoo|AUD ) and expecting to get result of all rows where prodCd is shampoo. QUERY 期望我的客户向我提供了 prodCd 和货币代码,例如 ( Shampoo|AUD ),并期望获得 prodCd 为 shampoo 的所有行的结果。 IMP NOTE: If the ProdCd currency is different from requested currency, prodValues should convertd value. IMP 注意:如果 ProdCd 货币与请求的货币不同,prodValues 应转换为值。

Rules for conversion,转换规则,

  1. If ItemId's prodValue needs to be converted, use itemIds OrderDate from ItemDetails table and use ExchangeRates table to do the conversion (Join on OrderDate and Exchange Date)如果 ItemId 的 prodValue 需要转换,使用ItemDetails表中的 itemIds OrderDate 并使用ExchangeRates表进行转换(Join on OrderDate and Exchange Date)
  2. (Part I don't know) If orderDate is not present in ExchangeRates table use the closest ExchangeRate . (部分我不知道)如果 ExchangeRates 表中不存在 orderDate ,请使用最接近的ExchangeRate (Get Closest exchange date to the order date and use that exchange rate). (获取最接近订单日期的交换日期并使用该汇率)。
  3. (Part I don't know) How can I write a query which covers all the conversion cases, (部分我不知道)如何编写一个涵盖所有转换案例的查询,
    3.1. 3.1。 Convert GBP product value to AUD?将英镑产品价值转换为澳元? As all conversion rates are in terms of USD.由于所有转换率均以美元计。 I understand that I need to convert GBP to USD (Using USD to GBP) and then convert USD to AUD (using USD to AUD rate)我了解我需要将英镑兑换成美元(使用美元兑换英镑),然后将美元兑换成澳元(使用美元兑换澳元汇率)
    3.2 User can request result in any currency. 3.2 用户可以请求任何货币的结果。 (Consider that exchange rate table has rates for all the currencies) (考虑汇率表有所有货币的汇率)

Here is what I got until now,这是我到目前为止得到的,

SELECT id.ItemId,    
       id.OfferingDate,     
       ipcv.Prodcd,     
Cast(Prodvalue AS DECIMAL(22, 8)) * er.ExchangeRate AS finalConvertedValue      
FROM   ExchangeRates er     
       JOIN ItemProdCodeValueMapping ipcv     
         ON er.SourceCurrency = ipcv.ProdCurrencyCd         
       JOIN Itemdetails id    
         ON ipcv.ItemId = id.ItemId
            AND id.OrderDate = er.ExchangeDate    
WHERE  er.TargetCurrency = 'AUD'     
       AND ProdCd = 'Shampoo'  

My end goal is to have a query which will cover all cases.我的最终目标是有一个涵盖所有情况的查询。

here how you can achieve this by using cross apply , second cross apply will give you the result in any provided currency:在这里,您如何通过使用cross apply来实现这一点,第二个 cross apply 将以任何提供的货币为您提供结果:

if there is no provided currency exchange for given currency, the target currency would be in USD:如果没有为给定货币提供货币兑换,则目标货币将为美元:

SELECT
    ipv.*
    , id.*
    , er.SourceCurrency
    , er.ExchangeDate
    , er.ExchangeRate
    , ipv.ProdValue * (1 / er.ExchangeRate)                    AS [ProdValue in USD]
    , er2.ExchangeDate [target exchnage date]
    , er2.ExchangeRate [target exchange rate]
    , ipv.ProdValue * (1 / ISNULL(er.ExchangeRate, 1)) * ISNULL(er2.ExchangeRate, 1) AS [ProdValue in target exchange]
FROM
    ItemDetail                    id
    JOIN ItemProdCodeValueMapping ipv
        ON ipv.ItemId = id.ItemId
    OUTER APPLY
    (
        SELECT TOP 1
            *
        FROM
            dbo.ExchangeRates AS er
        WHERE
            er.TargetCurrency = ipv.ProdCurrencyCd
            AND er.SourceCurrency = 'USD' -- to avoid converting USD
        ORDER BY
            ABS(DATEDIFF(DAY, ExchangeDate, id.OrderDate))
    ) er
    OUTER APPLY
    (
        SELECT TOP 1
            *
        FROM
            dbo.ExchangeRates AS er_target
        WHERE
            er_target.TargetCurrency = 'CAD'
        ORDER BY
            ABS(DATEDIFF(DAY, er_target.ExchangeDate, id.OrderDate))
    ) er2
WHERE
    ipv.ProdCd = 'Shampoo'

the other way of doing this, You could create a join with exchange table mapping target currency and get the same results另一种方法是,您可以使用交换表映射目标货币创建连接并获得相同的结果

 DECLARE @Prodcd nvarchar(30);  
 DECLARE @TargeCurrency nvarchar(30);  

 SET @Prodcd = 'Shampoo ';
 SET @TargeCurrency = 'CAD';
 select ItemDetails.ItemId,Prodcd,ItemProdCodeValueMapping.ProdValue,
 ProdCurrencyCd,ItemProdCodeValueMapping.ProdValue,ItemDetails.Orderdate
    ,(ItemProdCodeValueMapping.ProdValue *(1/ExchangeRates.ExchangeRate)) * TargetCurrency.ExchangeRate finalConvertedValue   

 from ItemProdCodeValueMapping 

 inner join ExchangeRates on ExchangeRates.TargetCurrency = ItemProdCodeValueMapping.ProdCurrencyCd

 inner join ItemDetails on ItemProdCodeValueMapping.ItemId = ItemDetails.ItemId and ItemDetails.Orderdate = ExchangeRates.ExchangeDate

 inner join (select top 1 TargetCurrency,ExchangeRate,ExchangeDate from  ExchangeRates where 
    TargetCurrency = @TargeCurrency order by ExchangeDate desc) as   TargetCurrency  on TargetCurrency.ExchangeDate <= ItemDetails.Orderdate
 
 where Prodcd = @Prodcd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM