艰难的T-SQL加入左边?

oJM*_*86o 6 t-sql sql-server-2005

我有一个ExchangeRates表,它有一个countryid和一个exchangerate,这个效果:

ExchangeRateID   Country   ToUSD      ExchangeRateDate
1                  Euro     .7400     2/14/2011
2                  JAP      80.1900   2/14/2011
3                  Euro     .7700      7/20/2011
Run Code Online (Sandbox Code Playgroud)

请注意,根据日期,可能会有相同的国家/地区具有不同的费率...因此,例如,在2011年2月14日欧元为0.7400,现在是.7700 7/20/2011.

我有另一个行项目表,用于根据国家/地区列出项目.在此表中,每个行项目都有一个与之关联的日期.订单项日期应根据汇率使用相应的日期和国家/地区.因此,如果我在2011年2月16日有一个国家/地区欧元的订单项,则使用上述数据时,应使用2011年2月14日的欧元值而不是7/20/2011的值,因为日期(条件er. ExchangeRateDate <= erli.LineItemDate).如果我在表中只有一个项目,但是假设我的订单项日期为8/1/2011那么这个条件(er.ExchangeRateDate <= erliLineItemDate)将返回多行,因此我的查询将失败...

SELECT     
    er.ExchangeRateID, 
    er.CountryID AS Expr1, 
    er.ExchangeRateDate, 
    er.ToUSD, 
    erli.ExpenseReportLineItemID, 
    erli.ExpenseReportID, 
    erli.LineItemDate
FROM         
    dbo.ExpenseReportLineItem AS erli 
LEFT JOIN
    dbo.ExchangeRate AS er 
ON er.CountryID = erli.CountryID 
AND DATEADD(d, DATEDIFF(d, 0, er.ExchangeRateDate), 0) <= DATEADD(d, DATEDIFF(d, 0, 
                      erli.LineItemDate), 0)
WHERE     (erli.ExpenseReportID = 196)
Run Code Online (Sandbox Code Playgroud)

这个左连接的问题是因为日期是<=行项目日期所以它返回许多记录,我不得不以某种方式做到这一点,但不知道如何.

LineItem表有多个记录,每个记录可以有自己的CountryID:

Item            Country      ParentID    LineItemDate
Line Item 1      Euro           1           2/14/2011
Line Item 2      US             1           2/14/2011
Line Item3       Euro           1           2/15/2011
Run Code Online (Sandbox Code Playgroud)

所以ParentID(ExpenseReportID)= 1有三条记录.那么我拿这些记录并加入ExchangeRate表,其中我的行项目表中的国家/地区=汇率表的国家/地区(该部分很容易)但是第二个条件我要做的是:

  AND DATEADD(d, DATEDIFF(d, 0, er.ExchangeRateDate), 0) <= DATEADD(d, DATEDIFF(d, 0, 
                          erli.LineItemDate), 0)
Run Code Online (Sandbox Code Playgroud)

但问题出在这里是因为这将从我的汇率表中返回多行,因为欧元列出了两次.

Tao*_*Tao 3

我可能在这里遗漏了一些东西,但据我了解,您的问题的“愚蠢”解决方案是使用 ROW_NUMBER 函数和外部过滤器与现有的“返回太多条目”查询(这也可以通过 CTE 来完成,但是对于像这样的简单情况,我更喜欢派生表语法):

SELECT *
FROM (
    SELECT     
        er.ExchangeRateID, 
        er.CountryID AS Expr1, 
        er.ExchangeRateDate, 
        er.ToUSD, 
        erli.ExpenseReportLineItemID, 
        erli.ExpenseReportID, 
        erli.LineItemDate,
        ROW_NUMBER() OVER (PARTITION BY ExpenseReportID, ExpenseReportLineItemID ORDER BY ExchangeRateDate DESC) AS ExchangeRateOrderID
    FROM dbo.ExpenseReportLineItem AS erli 
    LEFT JOIN dbo.ExchangeRate AS er 
        ON er.CountryID = erli.CountryID 
            AND DATEADD(d, DATEDIFF(d, 0, er.ExchangeRateDate), 0) 
                <= DATEADD(d, DATEDIFF(d, 0, erli.LineItemDate), 0)
    WHERE (erli.ExpenseReportID = 196)
        --For reasonable performance, it would be VERY nice to put a filter
        -- on how far back the exchange rates can go here:
        --AND er.ExchangeRateDate > DateAdd(Day, -7, GetDate())
) As FullData
WHERE ExchangeRateOrderID = 1
Run Code Online (Sandbox Code Playgroud)

抱歉,如果我误解了,否则希望这会有所帮助!