日期范围内的 Oracle sql 内部联接
Posted
技术标签:
【中文标题】日期范围内的 Oracle sql 内部联接【英文标题】:Oracle sql inner join on dates range 【发布时间】:2016-02-23 14:06:20 【问题描述】:我正在尝试编写加入 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 似乎离 56 年 1 月 29 日还有很长的路要走,该列中没有这样的日期 不知道是什么原因造成的这个问题
【问题讨论】:
CI.DATEINVOICED BETWEEN CCR.VALIDFROM AND CI.DATEINVOICED
始终为 TRUE,同一列两次...
所以你的意思是你得到BETWEEN
条件不是TRUE
的行?
您能否展示一些您收到的不正确数据的示例?另外,请确保您使用的查询是您在此处发布的。
第 16 年介于 11/12 和 56 之间。
如果您认为 29-JAN-56 没有日期,那么您可能会发现使用四位数年份掩码很有用;也许它不在您期望的世纪,或者您的查询仅查看 0056(取决于您的 NLS 设置)。查找该日期,和/或使用 4 位数年份重复您的查询,然后查看显示的内容。显示您查询的原始数据会很有帮助,日期再次显示全年(如果有时间,则时间不是 00:00)。
【参考方案1】:
看起来您的 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.
【讨论】:
以上是关于日期范围内的 Oracle sql 内部联接的主要内容,如果未能解决你的问题,请参考以下文章