Идентификация записей сторнирования, которые созданы более одного раза для фактической записи - PullRequest
0 голосов
/ 19 декабря 2018

Я использую пользовательский интерфейс для загрузки некоторых записей в базовые таблицы для проекта.В этом интерфейсе мне нужно создать реверсивную запись для фактической записи с последующим месяцем (периодом).По какой-то причине запись реверсирования дублировалась, и я мог видеть, что несколько реверсивных записей были загружены для одной реальной записи.Теперь я хочу идентифицировать записи сторнирования, которые были созданы более одного раза для реальной записи.

Пример: - данные моей таблицы выглядят так, как показано ниже

ID    Project   Emp No  Period  Hours    
--    -------   ------  ------  -----
 1     P1         E1    201810   10
 2     P1         E1    201811  -10
 3     P1         E1    201811  -10
 4     P1         E1    201811  -10

Теперь мне нужен SQL-запрос для определения записей сторнирования, которые произошли более одного раза (в данном случае ID 3,4).

Вывод запроса должен выглядеть следующим образом:

ID    Project   Emp No  Period  Hours    
--    -------   ------  ------  -----
 3     P1         E1    201811  -10
 4     P1         E1    201811  -10

Может кто-нибудь, пожалуйста, помогите мне сделать это ..

Ответы [ 5 ]

0 голосов
/ 20 декабря 2018

с заказом и rownum в подзапросе

select dt.ID,
       dt.Project,
       dt.Emp_No,
       dt.Period,
       dt.Hours from (    
select * from my_table order by Period desc) dt
where rownum <= 2
0 голосов
/ 20 декабря 2018

Это может быть разбито на три вида: (1) фактические транзакции (2) множественные аннулирования и (3) детали аннулирования

select dtl.* from 
  (select * from base_table where hours > 0) act,
  (select proj, emp, period, count(*), min(id) min_id 
   from base_table where hours < 0
   group by proj, emp, period having count(*) > 1) multi,
  (select * from base_table where hours < 0 ) dtl
where 
/* join actual transaction with multiple reversals.  NOTE: period clause below won't really handle year-month math */
act.emp = multi.emp
and act.proj = multi.proj
and to_number(act.period) + 1 = to_number(multi.period) 
/* find details of redundant reversals  */
and multi.min_id != dtl.id
and multi.emp = dtl.emp
and multi.proj = dtl.proj
and multi.period = dtl.period

Возможно, не самое эффективное решение, но оно должно работать (за исключением того, что ему нужен код для обработки фактического значения 201812, обратного в 201901)

0 голосов
/ 19 декабря 2018

Получите строки, которые не содержат минимум id каждой отдельной группы Project, EmpNo, Period, Hours:

SELECT t.* 
FROM tablename t
WHERE t.ID <> (
  SELECT MIN(tablename.ID) 
  FROM tablename 
  WHERE 
    tablename.Project = t.Project 
    AND 
    tablename.EmpNo = t.EmpNo 
    AND 
    tablename.Period = t.Period 
    AND 
    tablename.Hours = t.Hours
)
0 голосов
/ 19 декабря 2018

grouping by с условием having, как в следующем случае, отображает желаемый результат

with tab( ID, Project, EmpNo, Period, Hours ) as
    (
     select 1,'P1','E1',201810, 10 from dual union all
     select 2,'P1','E1',201811,-10 from dual union all
     select 3,'P1','E1',201811,-10 from dual union all
     select 4,'P1','E1',201811,-10 from dual
    )  
select *
  from tab
 where ID > 
  ( select min(ID)
      from tab
    group by Project, EmpNo, Period, Hours
    having count(*) > 1
     );

    ID  PROJECT EMPNO   PERIOD  HOURS
    --  ------- ------  ------  -----
    3   P1      E1      201811   -10
    4   P1      E1      201811   -10

Rextester Demo

0 голосов
/ 19 декабря 2018

Достаточно ли этого?

select t.*
from (select t.*
             row_number() over (partition by Project, EmpNo, Period, Hours order by id) as seqnum
      from t
     ) t
where seqnum >= 2;  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...