2016-12-05 60 views
2

我有一个表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行动代码的人,应该有一个长期行动代码记录也。例如:人员号码: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

你能分享预期的结果吗? –

+0

使用这一个内部查询'SELECT xx_WR.ACTION_CODE ACTION_CODE, COUNT(*)over(partition BY BY PERSON_NUM)ASFROM xx_WR' –

回答

0

查询来获取所有只action_code为RE,没有行动代码为针对同一人的TERM的人数。

如果我得到您的要求,您可以实现这一点使用不存在也。

SELECT * 
FROM xx_WR a 
WHERE a.ACTION_CODE='RE' 
AND not exists (select 1 
       from xx_WR b 
        where b.ACTION_CODE ='TERM' 
       and a.PERSON_NUM = b.PERSON_NUM) 
1

如果你只是想用一个RE操作代码的人,然后使用此:

SELECT t1.* 
FROM xx_wr t1 
INNER JOIN 
(
    SELECT PERSON_NUM 
    FROM xx_wr 
    GROUP BY PERSON_NUM 
    HAVING COUNT(*) = 1 
) t2 
    ON t1.PERSON_NUM = t2.PERSON_NUM 
WHERE t1.ACTION_CODE = 'RE' 

如果您也可以接受比一个动作的代码,只要TERM没有人针对出现的那个人,然后使用此:

SELECT t1.* 
FROM xx_wr t1 
INNER JOIN 
(
    SELECT PERSON_NUM 
    FROM xx_wr 
    GROUP BY PERSON_NUM 
    HAVING SUM(CASE WHEN ACTION_CODE = 'TERM' THEN 1 ELSE 0 END) = 0 AND 
      SUM(CASE WHEN ACTION_CODE = 'RE' THEN 1 ELSE 0 END) > 0 
) t2 
    ON t1.PERSON_NUM = t2.PERSON_NUM 
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记录的数量与PERSON_NUMTERM记录的数量。根据您的描述,听起来好像您可能能够获得一个案例,如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记录,并没有任期,你可以只再次小幅改变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