2015-10-30 4 views
1

У меня есть таблица Department_history и здесь подсчет записей для каждого отдела.запрос строки в Oracle 8i

select department_name, Id, count(1) total_rows_COUNT from Department_history 
where 
group by Department_history,id 
order by 2 desc 

результат:

department_name   ID  total_rows_COUNT 
Accounting   4564  556 
Finance    3434  671 
Marketing    4353 234 
IT     1233 454 

Я хочу сохранить только 10 записей для каждого отдела в таблице.

Если вы используете этот ниже запрос для каждого отдела, как это, он работает.

delete from Department_history a1 
where 
and a1.report_runtime NOT IN 
(
    select report_runtime 
    from (
     select a.*, rank() over (partition by department_name, id order by report_runtime desc) r 
     from Department_history a 
    ) rs 
    where r <= 10 and department_name = 'Accounting' 

) 
and department_name = 'Accounting' 

Но я не хочу отдельно запускать это удаление для каждого отдела. как я могу запустить один запрос, который удаляет данные для каждого имени отдела (если это> 10 записей). Я пытаюсь это сделать. но это не сработает.

delete from Department_history a1 
where 
and a1.report_runtime NOT IN 
(
    select report_runtime 
    from (
     select a.*, rank() over (partition by department_name, id order by report_runtime desc) r 
     from Department_history a 
    ) rs 
    where r <= 10 

) 

Может кто-нибудь посоветуете?

+0

Ваш первый запрос выбирает 2 столбца, но ваш выход 3? В вашем втором запросе «Department_history =« Учет »- правильное условие? Я думал, что это имя вашей таблицы, а не имя столбца. Работает ли синтаксис 'where and '? Неужели 'id' не имеет уникальных значений в вашей таблице Department_history? Если это не уникально, то именовать его 'id' действительно путают. Означает ли это уникальное имя department_name? Если да, то почему вы разделяете оба? Столбец report_runtime с уникальными значениями? Может быть, первичный ключ? – trincot

+1

В этом [скрипте SQL] (http://sqlfiddle.com/#!4/6643e/1) я помещал обобщенный оператор 'delete' на левой панели и' select' вправо, чтобы увидеть, удалил 3 записи, которые он должен удалить. Он работает правильно. Это Oracle 11g, поэтому, возможно, ваша проблема связана с Oracle 8i. Положите, пожалуйста, свою структуру таблицы (типы данных, первичный ключ, ...) – trincot

+0

просто думая об идентификаторе в разделе ... вам это действительно нужно? если вы хотите сгруппировать по имени_дектора, это выглядит так, что вы можете удалить идентификатор ... поэтому он должен быть завершен (раздел по порядку по порядку по порядку по report_runtime desc) – are

ответ

0

тестовый образец:

create table tst as select owner, view_name from all_views; 

delete from tst 
    where owner||'::'||view_name in 
( 
select owner||'::'||view_name from (
select owner, view_name, rank() over (partition by owner order by view_name) r from tst 
) where r > 10 
) 

ваш обновленный SQL:

delete from Department_history 
where id NOT IN 
(
    select id 
    from (
     select id, rank() over (partition by department_name 
order by report_runtime desc) rnk 
from Department_history 
    ) s 
    where s.rnk <= 10  
) 
+0

У ОП есть вопрос о таблице department_history, и вы отвечаете на что-то о all_views? намерены ответить на другой вопрос об удалении представлений базы данных? – trincot

+0

см. синтаксис ... не должно быть проблем с изменением имен таблиц, когда скрипт работает по мере необходимости – are

+0

'where (owner, view_name) in (select owner, view_na меня ...) 'было бы намного лучше, чем конкатенация –

0

Попробуйте это. Это похоже на то, что вы уже пробовали, но предложение not in должно проверять все 3 идентифицирующих столбца, department_name, id, report_runtime, а не только report_runtime. В противном случае вы можете случайно удалить неправильные строки.

Я также использовал row_number вместо rank. Я думаю, что это лучший выбор для вашего требования. Хотя, основываясь на вашем описании данных, я не думаю, что на самом деле это имеет значение в этом случае.

delete from department_history 
where (department_name, id, report_runtime) 
    not in (select department_name, id, report_runtime 
      from (select department_name, id, report_runtime, 
          row_number() over (partition by department_name, id order by report_runtime desc) as rn 
        from department_history) 
      where rn <= 10) 
+0

Я выполнил этот запрос за 1000 записей, и он работает. Спасибо! Теперь я выполняю этот в фактической таблице, которая имеет 600980 записей , и она работает более 30 минут, и она по-прежнему продолжается. Я создал индекс на имя_дедепа, id и report_runtime, но все равно не повезло. Я чувствую, что это длительное время выполнения для 600k записей – user5001305

+0

Лично мне нужно было сделать что-то вроде этого, я бы не попытался удалить такие строки. Я бы использовал подзапрос, чтобы создать новую таблицу только с теми данными, которые я хочу, затем отбросить исходную таблицу и наконец, переименует новую таблицу обратно в 'department_history'. Предполагая, что' select' работает эффективно, я думаю, что это будет работать намного быстрее. См. здесь для получения дополнительной информации: https://asktom.oracle.com/pls/apex/f ? p = 100: 11 ::: НЕТ: RP: P11_QUESTION_ID: 2345591157689 – sstan

+0

Это хорошая идея. Я думаю, это то, что я собираюсь делать. Спасибо за ваше время, чтобы проверить это. – user5001305

Смежные вопросы