簡體   English   中英

如何進行涉及子查詢的左連接?

[英]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上的左連接是非法的。 如果我放開連接,它會工作,但后來我錯過了最終結果中的一些事務。

請指教。

請注意:

  • 在單個查詢中實現這一點非常重要(帶有兩個查詢的兩步解決方案無濟於事)
    • 使用的數據庫是Sybase 12,雖然我認為這是一個通用的SQL東西
    • 這是一個簡化的模式,在我使用的實際查詢中,還有兩個這樣的轉換為不同金額所需的美元
    • 如果可能的話,請盡可能地針對現有查詢建議解決方案

謝謝你的時間。

這看起來很像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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM