[英]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,转换规则,
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)ExchangeRate
. (部分我不知道)如果 ExchangeRates 表中不存在 orderDate ,请使用最接近的ExchangeRate
。 (Get Closest exchange date to the order date and use that exchange rate). (获取最接近订单日期的交换日期并使用该汇率)。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.