假设我的oracle数据库中有两个表
表A:stDate,endDate,薪水
例如:
03/02/2010 28/02/2010 2000
05/03/2012 29/03/2012 2500
表B:DateOfActivation,rate
例如:
01/01/2010 1.023
01/11/2011 1.063
01/01/2012 1.075
我想有一个SQL查询,显示表A的工资总和,每个工资乘以表B的比率,具体取决于激活日期。
这里,对于第一个工资,优惠利率是第一个(1.023),因为第二个利率的激活日期晚于stDate和endDate间隔。 对于第二个工资,应用第三个工资,因为工资的激活日期在第二个工资的日期之间。
所以总和就是这个:2000 * 1.023 + 2500 * 1.075 = 4733.5
我希望我很清楚
由于
答案 0 :(得分:0)
假设速率必须在间隔开始之前有效(即DateOfActivation< stDate),你可以这样做(see fiddle):
SELECT SUM(salary*
(SELECT rate from TableB WHERE DateOfActivation=
(SELECT MAX(DateOfActivation) FROM TableB WHERE DateOfActivation < stDate)
)) FROM TableA;
答案 1 :(得分:0)
如果DateofActivation是具有rate_start_date和rate_end_date的真实有效日期表,则无法创建新行,其开始日期或end_date将位于现有的rate_start_date - rate_end_date对中,此问题变得更加容易。当前活动的行通常具有rate_end_date的NULL值。另外,可能,您希望工资表上的EMP_ID能够对行进行求和以完成计算;人们需要考虑以下情况:
Start Date is between rate_start and rate_end
End Date is between rate_start and rate_end
Rate_start and Rate_end are between start_date and end_date (sandwiched)
如果您运行以下代码段,您会看到我们可以按照以下方式人为创建rate_end_dates:
SELECT D.ACTIVEDATE, D.RATE, NVL(MIN(E.ACTIVEDATE)-1,SYSDATE) ENDDATE
FROM XX_DATEOFACTIVATION D, XX_DATEOFACTIVATION E
WHERE D.ACTIVEDATE<E.ACTIVEDATE(+)
GROUP BY D.ACTIVEDATE, D.RATE
ORDER BY D.ACTIVEDATE
建议的代码如下:
SELECT DISTINCT * FROM
(SELECT S.*, T.RATE, S.SALARY*T.RATE
FROM XX_SAL_HIST S,
(SELECT D.ACTIVEDATE, D.RATE, NVL(MIN(E.ACTIVEDATE)-1,SYSDATE) ENDDATE
FROM XX_DATEOFACTIVATION D, XX_DATEOFACTIVATION E
WHERE D.ACTIVEDATE<E.ACTIVEDATE(+)
GROUP BY D.ACTIVEDATE, D.RATE) T -- creating synthetic rate_end_date
WHERE S.STDATE BETWEEN T.ACTIVEDATE AND T.ENDDATE)
UNION
(SELECT S.*, T.RATE, S.SALARY*T.RATE
FROM XX_SAL_HIST S,
(SELECT D.ACTIVEDATE, D.RATE, NVL(MIN(E.ACTIVEDATE)-1,SYSDATE) ENDDATE
FROM XX_DATEOFACTIVATION D, XX_DATEOFACTIVATION E
WHERE D.ACTIVEDATE<E.ACTIVEDATE(+)
GROUP BY D.ACTIVEDATE, D.RATE) T -- creating synthetic rate_end_date
WHERE S.ENDDATE BETWEEN T.ACTIVEDATE AND T.ENDDATE)
UNION
(SELECT S.*, T.RATE, S.SALARY*T.RATE
FROM XX_SAL_HIST S,
(SELECT D.ACTIVEDATE, D.RATE, NVL(MIN(E.ACTIVEDATE)-1,SYSDATE) ENDDATE
FROM XX_DATEOFACTIVATION D, XX_DATEOFACTIVATION E
WHERE D.ACTIVEDATE<E.ACTIVEDATE(+)
GROUP BY D.ACTIVEDATE, D.RATE) T -- creating synthetic rate_end_date
WHERE T.ACTIVEDATE BETWEEN S.STDATE AND S.ENDDATE)
答案 2 :(得分:0)
要做的第一件事是转换Table B
(查询中的Table2
),以便为每一行开始和结束日期
Select DateOfActivation AS startDate
, rate
, NVL(LEAD(DateOfActivation, 1) OVER (ORDER BY DateOfActivation)
, TO_DATE('9999/12/31', 'yyyy/mm/dd')) AS endDate
From Table2
现在我们可以使用Table A
(查询中的Table1
)
WITH Rates AS (
Select DateOfActivation AS startDate
, rate
, NVL(LEAD(DateOfActivation, 1) OVER (ORDER BY DateOfActivation)
, TO_DATE('9999/12/31', 'yyyy/mm/dd')) AS endDate
From Table2)
Select SUM(s.salary * r.rate)
From Rates r
INNER JOIN Table1 s ON s.stDate < r.endDate AND s.endDate > r.startDate
JOIN
条件会使Table A
中的每一行至少部分处于费率的激活期内,如果您需要包含它,则可以按以下查询更改1}}
WITH Rates AS (
Select DateOfActivation AS startDate
, rate
, NVL(LEAD(DateOfActivation, 1) OVER (ORDER BY DateOfActivation)
, TO_DATE('9999/12/31', 'yyyy/mm/dd')) AS endDate
From Table2)
Select SUM(s.salary * r.rate)
From Rates r
INNER JOIN Table1 s ON s.stDate >= r.startDate AND s.endDate <= r.endDate