[英]How to have a left join involving a sub query?
請幫助解決我在單個查詢中正確連接幾個表時遇到的問題 。
簡化的架構如下:
TRANSACTION TABLE:
-----------------
TRANSACTION_DATE AMOUNT CURRENCY
---------------- ---------- --------
22/09/13 100 EUR
22/09/13 200 FRA
22/09/13 200 GBP
CURRENCY_CONVERSION TABLE:
-------------------------
FROM_CURRENCY TO_CURRENCY CONVERSION_DATE CONVERSION_RATE
------------- ----------- --------------- ---------------
GBP USD 23/09/13 1.61
EUR USD 22/09/13 1.35
目前,有效的查詢如下(使用Sybase / SQL Server連接語法)
SELECT
t.transaction_date,
t.amount,
t.currency,
t.amount * cc.conversion_rate as amount_usd
FROM transaction t, currency_conversion cc,
WHERE t.transaction_date *= cc.conversion_date
AND t.currency *= cc.from_currency
AND cc.to_currency = 'USD'
當currency_conversion表可能沒有特定日期的轉換率時,我們在上述查詢中遇到問題。 在這種缺失值的情況下,企業希望采用DB中可用的最新轉換率。 例如,如果今天無法使用歐元兌美元匯率,請使用昨天的匯率。 我嘗試按如下方式執行此操作:
SELECT
t.transaction_date,
t.amount,
t.currency,
t.amount * cc.conversion_rate as amount_usd
FROM transaction t, currency_conversion cc,
WHERE t.transaction_date *=
(SELECT max(c1.conversion_date) FROM currency_conversion c1
WHERE c1.from_currency = t.from_currency
AND c1.to_currency = 'USD')
AND t.currency *= cc.from_currency
AND cc.to_currency = 'USD'
此查詢不起作用。 t.transaction_date上的左連接是非法的。 如果我放開連接,它會工作,但后來我錯過了最終結果中的一些事務。
請指教。
請注意:
謝謝你的時間。
這看起來很像T-SQL Subquery Max(Date)和Joins 。 那沒用嗎?
(對不起,我還不能評論!)
制作一個(臨時的,如果需要的)表格是否合理? 也就是說,生成一個您可能需要的所有日期的列表,然后用一個INSERT
循環填充表格,以便您知道您的聯接將始終與合作伙伴匹配? 這是一個額外的前期成本和更長的連接,但它是一個更簡單的連接,應該很快與適當的索引。
據我所知Sybase也支持窗口函數。 我能想到的最好的是:
select transaction_date,
amount,
currency,
conversion_rate,
conversion_date as effective_conversion_date,
amount_usd
from (
select t.transaction_date,
t.amount,
t.currency,
cc.conversion_rate,
cc.conversion_date,
t.amount * cc.conversion_rate as amount_usd,
dense_rank() over (partition by transaction_date, currency order by cc.conversion_date desc) as rn,
max(cc.conversion_date) over (partition by currency) as max_conv_date
from transactions t
left join currency_conversion cc
on t.currency = cc.from_currency
and cc.to_currency = 'USD'
) t
where (conversion_date = max_conv_date or rn = 1)
order by transaction_date;
訣竅是從外連接中省略transaction_date並使用窗口函數動態計算最新的conversion_date。 同時, dense_rank()
將值應用於“最新”轉換日期。 如果該貨幣有多個currency_conversions,那么將為單個事務返回多行。
然后,通過僅選擇transaction_date等於最新轉換日期或具有最新轉換日期的行來過濾掉那些不需要的行。
但是 :我認為這不是很有效。 如果你的表非常大(我猜這是預期的),這可能表現不佳。
這是一個小小的SQL Fiddle示例: http ://sqlfiddle.com/#!12 / 63ef4 / 1
(它使用的是Postgres和ANSI SQL,但我認為查詢也應該在Sybase上運行)
子查詢沒有在兩個表之間進行連接,它只是選擇一個日期......這不是你真正想要的動作。
如果我理解正確,您需要為具有最新日期的記錄選擇轉換率,然后在乘法中使用它。
SELECT
t.transaction_date,
t.amount,
t.currency,
t.amount * (SELECT cc.conversion_rate FROM currency_conversion cc
WHERE cc.from_currency = t.from_currency
AND cc.to_currency = 'USD'
AND cc.conversion_date = (SELECT max(c1.conversion_date) FROM
FROM currency_conversion c1
WHERE c1.conversion_date <=
t.transaction_date)) as amount_usd
FROM transaction t
如果你的currency_conversion表有開始和結束日期,你可以擺脫c1子查詢,只需將cc子查詢集中在范圍內的日期和<= transaction_date,這將簡化事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.