Удалить все, кроме некоторых строк - Oracle - PullRequest
4 голосов
/ 27 ноября 2009

Я хочу удалить множество строк из таблицы. Я могу решить, какие строки должны быть удалены. Я буду удалять строки из таблицы, только если количество строк больше 5 (в зависимости от условия).

Рассмотрим этот пример данных

ID--Col1--Col2--
1   A      X
2   A      X
3   A      X
4   A      X
5   A      X
6   A      X
7   A      X
8   A      X
9   A      X
10   A      X
11   B      X
12   B      X
13   B      X
14   B      X
15   C      X
16   C      X
17   C      X
18   D      X
19   D      X

Я хочу удалить 5 строк {*, A, X}, мне нужно сохранить 5 из них (независимо от того, какая из них). Я не буду удалять B, C & D, поскольку их количество меньше 5.

Как

delete from tableA
 --- I can decide on the rows to delete based on two conditions.
 where col1 = someCondition
   and col2 = someOtherCondition
   and rownum > 5 --- This dint work. I checked.

Я думаю, возможно, мне нужно программно. Любые предложения с благодарностью.

Ответы [ 5 ]

9 голосов
/ 27 ноября 2009

Это удалит все строки для каждой уникальной комбинации col1 и col2, кроме первых пяти, упорядоченных по rowid

delete from my_table
where rowid in
  (
  select rowid
  from
    (
    select rowid,
           row_number() over (partition by col1, col2 order by rowid) rownumber
    from   my_table
    )
  where rownumber > 5
  )
/
7 голосов
/ 27 ноября 2009

это удалит все строки кроме 20 строк, которые удовлетворяют обоим условиям на Col1 и Col2:

DELETE FROM tableA
 WHERE ROWID NOT IN (SELECT ROWID
                       FROM tableA
                      WHERE col1 = someCondition
                        AND col2 = someOtherCondition
                        AND rownum <= 20)

Если ваш набор данных действительно большой, следующее может быть быстрее:

CREATE tableTemp as 
SELECT *
  FROM tableA
 WHERE col1 = someCondition
   AND col2 = someOtherCondition
   AND rownum <= 20;

TRUNCATE tableA;

INSERT INTO tableA (SELECT * FROM tableTemp);

Замените усечение на УДАЛИТЬ, если вам нужен доступ к данным во время операции.

2 голосов
/ 27 ноября 2009

Это позволит сохранить максимум 5 от каждой группы:

delete mytable where rowid in
( select rowid from
  ( select rowid, row_number() over (partition by col1, col2 order by id) rn
    from mytable
  )
  where rn > 5
);
0 голосов
/ 22 июня 2013

Чтобы сохранить ЛЮБЫЕ 500 строк в таблице и удалить остальные.

delete from tablenameX where rownum <= (select count(*) - 500 from tablenamex);

Выше sql рекомендуется только если количество строк мало. Если большой, то используйте предложенный ранее подход к созданию временной таблицы.

0 голосов
/ 27 ноября 2009

ROWNUM> 5 не работает, потому что для первой затронутой строки ROWNUM всегда равен 1; это условие также включает в себя часть «ROWNUM> 5», поэтому Oracle не может найти строку, соответствующую требованиям.

Это может сработать:

delete from tableA
 --- I can decide on the rows to delete based on two conditions.
 where col1 = someCondition
   and col2 = someOtherCondition
   and rownum <= (select count(*) from tableA 
                    where col1 = someCondition
                      and col2 = someOtherCondition) - 5;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...