日期范围

时间:2016-02-23 14:06:21

标签: sql oracle join

我正在尝试编写加入id和日期范围的联接:

SELECT * FROM C_INVOICE CI 
INNER JOIN C_CONVERSION_RATE CCR 
    ON CCR.C_CURRENCY_ID=CI.C_CURRENCY_ID 
    AND CI.DATEINVOICED BETWEEN CCR.VALIDFROM AND CCR.VALIDTO

但我得到的结果只是来自

ON CCR.C_CURRENCY_ID=CI.C_CURRENCY_ID 

理论上这应该可以正常工作,我没有任何错误,但结果不是我想要的

修改

--Full query
SELECT * FROM C_INVOICE CI 
INNER JOIN C_CONVERSION_RATE CCR 
    ON CCR.C_CURRENCY_ID=CI.C_CURRENCY_ID 
    AND CI.DATEINVOICED BETWEEN CCR.VALIDFROM AND CCR.VALIDTO
WHERE CI.C_INVOICE_ID='1019748';

CI.DATEINVOICED = 15-FEB-16 CI.C_CURRENCY_ID = 100

C_CONVERSION_RATE表中有很多行,C_CURRENCY_ID = 100 但只有一行属于间隔。

CI.DATEINVOICED(15-FEB-16) BETWEEN CCR.VALIDFROM(15-FEB-16) AND CCR.VALIDTO(15-FEB-16)

在这个特定情况下,CCR.VALIDFROM,CCR.VALIDTO都等于同一日期15-FEB-16,但在其他情况下它可以是几天间隔

无论如何,我期待的结果是货币ID和日期间隔匹配的单行。但是,我得到货币ID匹配的所有行。

修改

稍微修改了查询

SELECT 
ci.dateinvoiced,
ccr.validfrom,
ccr.validto
FROM C_INVOICE CI 
INNER JOIN C_CONVERSION_RATE CCR 
    ON CCR.C_CURRENCY_ID=CI.C_CURRENCY_ID 
    AND CI.DATEINVOICED BETWEEN CCR.VALIDFROM AND CCR.VALIDTO
WHERE CI.C_INVOICE_ID='1019748';

此查询的结果我正在

    15-FEB-16   07-MAR-11   29-JAN-56
    15-FEB-16   02-MAR-11   29-JAN-56
    15-FEB-16   27-MAR-11   29-JAN-56
    15-FEB-16   07-FEB-11   29-JAN-56
    15-FEB-16   18-JAN-12   29-JAN-56

ccr.validto似乎离开了29-JAN-56,该列中没有这样的日期 不知道造成这个问题的原因

1 个答案:

答案 0 :(得分:0)

看起来您的C_CONVERSION_RATE表包含许多行,其VALIDTO日期代表任意结束时间值29-JAN-59(世纪未知)。如果您要查找相对于DATEINVOICED的最近有效转换率,您可能需要使用分析函数来确定下一个有效的VALIDFROM值:

WITH CCR AS (
  SELECT CCR.*
       , LEAD(CCR.VALIDFROM,1,CCR.VALIDTO) 
         OVER (PARTITION BY CCR.C_CURRENCY_ID 
                   ORDER BY CCR.VALIDFROM
                          , CCR.VALIDTO
         ) VALID_TO  -- note the underscore ;)
    FROM C_CONVERSION_RATE CCR
)
SELECT *
  FROM C_INVOICE CI 
 INNER JOIN CCR 
    ON CCR.C_CURRENCY_ID=CI.C_CURRENCY_ID 
   AND CI.DATEINVOICED BETWEEN CCR.VALIDFROM AND CCR.VALID_TO -- note the underscore
   AND CI.DATEINVOICED <> CCR.VALID_TO -- Make it a half open interval by not
                                       -- including the exact end date since
                                       -- it is actually the next start date.