我有两个类似于下面的示例表的表。 PAY
表显示员工的薪酬和时间。 ENROLL
表显示员工注册的时间'E'
以及之后何时终止'T'
。因此,在这种情况下,员工从3/1/14
注册到5/31/14
,然后再次从10/01/14
注册到11/30/14
。
EMPLID PAY_END_DT PAY_AMT
00100001 31-JAN-14 110
00100001 28-FEB-14 120
00100001 31-MAR-14 130 <-- should be included in SUM
00100001 30-APR-14 140 <-- should be included in SUM
00100001 31-MAY-14 150 <-- should be included in SUM
00100001 30-JUN-14 160
00100001 31-JUL-14 170
00100001 31-AUG-14 180
00100001 30-SEP-14 190
00100001 31-OCT-14 200 <-- should be included in SUM
00100001 30-NOV-14 210 <-- should be included in SUM
00100001 31-DEC-14 220
EMPLID EFFDT STATUS
00100001 01-MAR-14 E
00100001 31-MAY-14 T
00100001 01-OCT-14 E
00100001 30-NOV-14 T
我想要的是一个SQL,它会对PAY_AMT
列求和,但仅适用于在注册员工时发生PAY_AMT
个PAY_END_DT
的{{1}}。例如,在这种情况下,我只想将PAY_AMT
的{{1}}与PAY_END_DT
到3/1/14
或5/31/14
10/01/14
内的11/30/14
相加{1}}。所以,正确的结果将是:
EMPLID SUM
00100001 830
我需要为许多不同的EMPLID
运行此SQL,其中一些可能有两个注册周期,如此示例,其他可能有零个,一个,三个或更多注册周期。
我曾考虑使用lead()
,但在这种情况下无法弄清楚如何使用它。我还考虑过使用between...and...
,但由于注册时间可能会有所不同,因此我不知道如何处理。
我不想使用PL / SQL。
为了使事情变得更容易,下面是这两个表的模板:
WITH
PAY AS(
SELECT '00100001' AS EMPLID, TO_DATE('2014-01-31', 'YYYY-MM-DD') AS PAY_END_DT, 110.00 AS PAY_AMT FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-02-28', 'YYYY-MM-DD'), 120.00 AS PAY_AMT FROM DUAL
UNION ALL
--SUM column would include this PAY_AMT
SELECT '00100001', TO_DATE('2014-03-31', 'YYYY-MM-DD'), 130.00 AS PAY_AMT FROM DUAL
UNION ALL
--SUM column would include this PAY_AMT
SELECT '00100001', TO_DATE('2014-04-30', 'YYYY-MM-DD'), 140.00 AS PAY_AMT FROM DUAL
UNION ALL
--SUM column would include this PAY_AMT
SELECT '00100001', TO_DATE('2014-05-31', 'YYYY-MM-DD'), 150.00 AS PAY_AMT FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-06-30', 'YYYY-MM-DD'), 160.00 AS PAY_AMT FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-07-31', 'YYYY-MM-DD'), 170.00 AS PAY_AMT FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-08-31', 'YYYY-MM-DD'), 180.00 AS PAY_AMT FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-09-30', 'YYYY-MM-DD'), 190.00 AS PAY_AMT FROM DUAL
UNION ALL
--SUM column would include this PAY_AMT
SELECT '00100001', TO_DATE('2014-10-31', 'YYYY-MM-DD'), 200.00 AS PAY_AMT FROM DUAL
UNION ALL
--SUM column would include this PAY_AMT
SELECT '00100001', TO_DATE('2014-11-30', 'YYYY-MM-DD'), 210.00 AS PAY_AMT FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-12-31', 'YYYY-MM-DD'), 220.00 AS PAY_AMT FROM DUAL
),
ENROLL AS (
SELECT '00100001' AS EMPLID, TO_DATE('2014-03-01', 'YYYY-MM-DD') AS EFFDT, 'E' AS STATUS FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-05-31', 'YYYY-MM-DD'), 'T' FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-10-01', 'YYYY-MM-DD'), 'E' FROM DUAL
UNION ALL
SELECT '00100001', TO_DATE('2014-11-30', 'YYYY-MM-DD'), 'T' FROM DUAL
)
答案 0 :(得分:3)
您对lead()
的猜测是正确的,解决方案非常简单:
with pay as (...),
enroll as (...)
select pay.emplid, sum(pay_amt)
from pay,
(select emplid, effdt effdt_start, status,
lead(effdt, 1) over (partition by emplid order by effdt) effdt_end
from enroll) enr
where enr.emplid = pay.emplid
and enr.status = 'E'
and pay.pay_end_dt between enr.effdt_start and enr.effdt_end
group by pay.emplid;