我有一张表xx_wr:
PERSON_NUM ACTION_CODE EFF_START_DATE EFF_END_DATE
10 RE 01-JAN-2016 31-DEC-4712
12 TERM 02-FEB-2016 01-MAR-2016
12 RE 02-MAR-2016 31-DEC-4712
理想情况下,当有人的RE动作代码时,也应该有一个TERM动作代码记录。例如:人数:12 我正在查询只将action_code作为RE获取所有人,并且没有针对相同人员编号的行动代码作为TERM。例如:10
SELECT *
FROM
( SELECT xx_WR.ACTION_CODE ACTION_CODE,
ROW_NUMBER() over (partition BY PERSON_NUM
ORDER BY ACTION_CODE) AS rn
FROM xx_WR ) T
WHERE RN =1
AND ACTION_CODE='RE';
此查询返回12和10.它应该只选择10,因为我们在此表中将action_code作为“RE”并且没有“TERM”行获取这些人员编号。
答案 0 :(得分:1)
SELECT *
FROM
(
SELECT
*
,ROW_NUMBER() OVER (PARTITION BY PERSON_NUM, ACTION_CODE ORDER BY EFF_END_DATE DESC) as rn
,COUNT(CASE WHEN ACTION_CODE = 'RE' THEN 1 END) OVER (PARTITION BY PERSON_NUM) as RECount
,COUNT(CASE WHEN ACTION_CODE = 'TERM' THEN 1 END) OVER (PARTITION BY PERSON_NUM) as TERMCount
FROM
xx_WR
) t
WHERE
t.rn = 1
AND t.ACTION_CODE = 'RE'
AND t.RECount > t.TERMCount
所以ROW_NUMBER()
只做那个,它构建一个行号。实际上,您需要比较每RE
个TERM
条记录与PERSON_NUM
条记录的数量。根据您的描述,听起来您可能会得到RE -> TERM -> RE
之类的案例,然后您又想要返回该案例。无论如何,在这里使用窗口函数非常棒,尤其是当您与条件聚合合作时。另请注意,此解决方案将处理RE -> RE
情况并仍返回最新的RE记录。
请注意,如果您只想查找没有任何条款记录的情况,您可以进行调整:
SELECT *
FROM
(
SELECT
*
,ROW_NUMBER() OVER (PARTITION BY PERSON_NUM, ACTION_CODE ORDER BY EFF_END_DATE DESC) as rn
,COUNT(CASE WHEN ACTION_CODE = 'RE' THEN 1 END) OVER (PARTITION BY PERSON_NUM) as RECount
,COUNT(CASE WHEN ACTION_CODE = 'TERM' THEN 1 END) OVER (PARTITION BY PERSON_NUM) as TERMCount
FROM
xx_WR
) t
WHERE
t.rn = 1
AND t.ACTION_CODE = 'RE'
AND t.TERMCount = 0
如果你只想要一个拥有1条RE记录且没有TERM的人你可以再次稍微更改where子句,或者你也不再需要行号,这样你就可以这样做:
SELECT *
FROM
(
SELECT
*
,COUNT(CASE WHEN ACTION_CODE = 'RE' THEN 1 END) OVER (PARTITION BY PERSON_NUM) as RECount
,COUNT(CASE WHEN ACTION_CODE = 'TERM' THEN 1 END) OVER (PARTITION BY PERSON_NUM) as TERMCount
FROM
xx_WR
) t
WHERE
t.ACTION_CODE = 'RE'
AND t.RECount = 1
AND t.TERMCount = 0