Sql 查询以仅获取某人的行

Sql 查询以仅获取某人的行,sql,oracle,Sql,Oracle,我有一张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-MA

我有一张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
理想情况下,当一个人有重复动作代码时,也应该有一个术语动作代码记录。例如:人数:12 我正在查询,以获取针对同一个人编号的所有人员,其中只有作为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,因为我们正在获取此表中操作代码为“RE”且没有“TERM”行的人号。

如果您只需要具有单个
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'
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
如果您还可以接受具有多个操作代码的人员,只要
术语
没有针对该人员出现,则使用以下方法:

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'
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
因此,
ROW\u NUMBER()
仅此而已,它构建了一个行号。实际上,您需要比较每个
人数的
RE
记录数与
TERM
记录数。根据您的描述,听起来您可能能够获得一个案例,例如
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个重新记录,而没有术语,您可以再次稍微更改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

查询以获取针对同一人号的所有人员,其中只有作为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)

您能否共享预期结果。内部查询使用此查询
选择xx_WR.ACTION_code ACTION_code,COUNT(*)over(partition BY PERSON_NUM)AS rn FROM xx_WR