Oracle SQL - Отображение только net строк эффекта (не соответствует) - PullRequest
1 голос
/ 02 марта 2020

Ниже приводится пример структуры моей таблицы

Name    Amount
A          100
A          100
A         -100
A          100
A          100
A         -100
B           10
A          100

В этой таблице нет первичного ключа.

Желаемый результат:

Name    Amount
A          100
A          100
B           10
A          100

Объяснение: Мне нужно отменить соответствующие строки, т. е. один -100 обнуляет один +100. Поэтому мне нужно отображать только строки, которые не смещены / не обнуляются один к одному.

Это можно сделать в PL / SQL, заполнив строки во временной таблице и удалив one положительный для каждого одного соответствующего отрицательного. Тем не менее, я требую сделать это на лету, используя SQL заявления.

С уважением, Рагу

Ответы [ 3 ]

1 голос
/ 02 марта 2020

Вы можете присвоить каждой строке ROW_NUMBER, уникальную для этой пары name / amount, и затем посчитать, есть ли для name / ABS(amount) одно или два значения для каждого из этих ROW_NUMBER и отбросьте строки, где есть две (одна положительная и одна отрицательная):

SELECT name,
       amount
FROM   (
  SELECT name,
         amount,
         COUNT( amount ) OVER ( PARTITION BY name, ABS( amount ), rn )
           AS num_matches
  FROM   (
    SELECT t.*,
           ROW_NUMBER() OVER ( PARTITION BY name, amount ORDER BY ROWNUM ) AS rn
    FROM   table_name t
  )
)
WHERE num_matches = 1

Итак, для ваших выборочных данных:

CREATE TABLE table_name ( Name, Amount ) AS
SELECT 'A', +100 FROM DUAL UNION ALL
SELECT 'A', +100 FROM DUAL UNION ALL
SELECT 'A', -100 FROM DUAL UNION ALL
SELECT 'A', +100 FROM DUAL UNION ALL
SELECT 'A', +100 FROM DUAL UNION ALL
SELECT 'A', -100 FROM DUAL UNION ALL
SELECT 'B',  +10 FROM DUAL UNION ALL
SELECT 'A', +100 FROM DUAL;

Это выводит:

NAME | AMOUNT
:--- | -----:
A    |    100
A    |    100
A    |    100
B    |     10

дБ <> скрипка здесь

1 голос
/ 02 марта 2020

Вы можете перечислить строки, используя row_number(), а затем использовать их для их "отмены":

select t.name, t.amount
from (select t.*,
             sum(amount) over (partition by name, abs(amount), seqnum) as sum_amount
      from (select t.*,
                   row_number() over (partition by name, amount order by name) as seqnum
            from t
           ) t
      ) t
where sum_amount <> 0;

Здесь - это скрипта db <>.

0 голосов
/ 02 марта 2020

Если никогда не бывает больше отрицательных значений, чем положительных, это задача ЗА ИСКЛЮЧЕНИЕМ ВСЕ. Oracle не поддерживает, но это переписать:

select name, amount
from
 (
   select name, amount, row_number() over (partition by name, amount order by amount)
   from tab
   where amount > 0
   minus
   select name, -amount, row_number() over (partition by name, amount order by amount)
   from tab
   where amount < 0
 ) dt

или

with cte as 
 (
   select name, amount, row_number() over (partition by name, amount order by amount) as rn
   from tab
 )
select name, amount
from
 (
   select name, amount, rn
   from cte
   where amount > 0
   minus
   select name, -amount, rn
   from cte
   where amount < 0
 ) dt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...