SELECT B.TERM TERMB,DATEDIFF(T.MATURITY,T.DATA_DT)/365 TERMT,D.TERM TERMD
FROM T_MAIN T
LEFT JOIN T_B B
##正常的唯一确定关联条件
ON B.DATA_DT=T.DATA_DT
AND CONCAT(T.CURRENCY,'/CNY')=B.CURRENCY
##通过主表的期限点,需要找出副表的相邻期限点(小于目标的最大期限点)
AND B.TERM=(SELECT MAX(TERM+0) FROM T_B
WHERE DATA_DT=T.DATA_DT AND (TERM+0)<DATEDIFF(T.MATURITY,T.DATA_DT)/365)
LEFT JOIN T_D D
##正常的唯一确定关联条件
ON D.DATA_DT=T.DATA_DT
AND CONCAT(T.CURRENCY,'/CNY')=D.CURRENCY
##通过主表的期限点,需要找出副表的相邻期限点(大于目标的最小期限点)
AND D.TERM=(SELECT MIN(TERM+0) FROM T_D
WHERE DATA_DT=T.DATA_DT AND (TERM+0)>DATEDIFF(T.MATURITY,T.DATA_DT)/365)
——20211019更新——
上面的方法在MYSQL和ORACLE中都满足查询,但是在编译存储过程时对两数据库的支持有偏差;在MYSQL可以正常编译通过存储过程,而在ORACLE存储过程编译时会报错:ORA-01799 列不能外部联接到子查询。这是因为在oracle中关联条件on中不能在嵌套子查询,所以不能用这种方法。
对于oracle可以选用一下方法实现同样效果:
ORACLE语法:
SELECT
B.TERM TERMB,
(T.MATURITY-T.DATA_DT)/365 TERMT,
D.TERM TERMD
FROM T_MAIN T
/*
LEFT JOIN T_B B
##正常的唯一确定关联条件
ON B.DATA_DT=T.DATA_DT
AND CONCAT(T.CURRENCY,'/CNY')=B.CURRENCY
##通过主表的期限点,需要找出副表的相邻期限点(小于目标的最大期限点)
AND B.TERM=(SELECT MAX(TERM+0) FROM T_B
WHERE DATA_DT=T.DATA_DT AND (TERM+0)<DATEDIFF(T.MATURITY,T.DATA_DT)/365)
此处再用ON条件去取最大值就不合适了 会报错
*/
LEFT JOIN
(SELECT DATA_DT,CURVEID, MIN(TERM) AS TERM
FROM T_B
--WHERE (T.ENDDT-T.STARTDT)/365<TERM “报错”
--在子查询过滤条件中不能引用子查询外部的表字段
GROUP BY DATA_DT,CURVEID,TERM) B
ON T.DATA_DT=B.DATA_DT
AND T.CURVEID=B.CURVEID
--此方法也可以找出副表中最大期限或最小期限,但缺点是子查询B的内部无法引用主表中的关键字段,只适用于主表和副表有明确关联条件的场景
LEFT JOIN
(SELECT DATA_DT,CURVEID, MAX(TERM) AS TERM
FROM T_B
--WHERE (T.ENDDT-T.STARTDT)/365<TERM “报错”
--在子查询过滤条件中不能引用子查询外部的表字段
GROUP BY DATA_DT,CURVEID,TERM) D
ON T.DATA_DT=D.DATA_DT
AND T.CURVEID=D.CURVEID;
/*
如果一定想通过max,min来得出所要结果只能再来回套子查询,做临时表,应该是会比较麻烦
*/
第三种方法是用了分组排序来找出每条数据对应的两个端点
SELECT T0.*,RN
FROM (
SELECT
B.TERM TERMB,
(T.ENDDT-T.STARTDT)/365 TERMT,
D.TERM TERMD,
ROW_NUMBER() OVER(PARTITION BY T.TRADENO ORDER BY B.TERM DESC,D.TERM ASC) RN
FROM T_MAIN T
LEFT JOIN T_B B
##正常的唯一确定关联条件
ON B.DATA_DT=T.DATA_DT
AND B.CURVEID=T.CURVEID
##通过主表的期限点,需要找出副表的相邻期限点
AND B.TERM<(T.ENDDT-T.STARTDT)/365
LEFT JOIN T_D D
##正常的唯一确定关联条件
ON D.DATA_DT=T.DATA_DT
AND B.CURVEID=T.CURVEID
##通过主表的期限点,需要找出副表的相邻期限点
AND D.TERM>=(T.ENDDT-T.STARTDT)/365
) T0
WHERE T0.RN=1
这种方法通过对一个已知期限点两端小于它和大于它的市场期限都找出来,然后按照小期限倒序、大期限正序的方法分组排序后取第一即待求期限相近的两个左右期限端点。缺点是在排序之前会产生大量乘积数据,每一条数据会得到(小于该期限的市场数据记录数)*(大于该期限的市场数据记录数)条中间记录,然后只选取一条输出结果。数据量大的时候应该会比较影响效率,适合数据量不大的场景使用。
目前还没想到其他有效的处理逻辑,想到了再补充。