![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Снова про удаление дублей в таблице
Vlad © (2004-02-10 13:44:00)
Доброго всем времени суток.
Вот тут не так давно мне посоветовали для удаления дублирующих записей в таблице использовать конструкцию вида:
delete from table t1 where
1<(select count(*) from table t2 where t2.поле1=t1.поле1 and t2.поле2=t1.поле2)
Такая конструкция обеспечивала уникальность связки полей Поле1+Поле2.
На IB запрос работал прекрасно, но вот на Oracle он удаляет не только дублирующие, но и основные записи.
Подскажите, в чем может быть дело ? Возможно ли как-то решить эту проблему с помощью настроек оптимизатора, или доп. хинтов в запросе ?
Sandman25 (2004-02-10 18:53:00) [1]
[14] Vlad © (10.02.04 18:52)
Насколько я знаю, такое проходит только для семейства IB. Во всех остальных SQL СУБД такое не проходит. Так что дело не в Oracle...
Vlad (2004-02-10 18:52:00) [2]
Спасибо всем кто откликнулся.
Я понимаю, что это можно сделать другими способами, но меня в данном случае интересуют не другие способы, а то, почему этот способ не проходит в Oracle и как его заставить работать. Вопрос принципа так сказать :-)
Но видимо не получится :-(
Sandman25 (2004-02-10 18:36:00) [3]
[12] panov © (10.02.04 18:28)
Вы вроде бы участвовали в sql.ipps.ru, после того конкурса такие select воспринимаются достаточно легко :)
panov (2004-02-10 18:28:00) [4]
-))))
Sandman25 (2004-02-10 18:21:00) [5]
delete from table1
where rowid <>
(select min(rowid)
from table1 t2
where t2.field1=table1.field1
and t2.field2=table2.field2
)
panov (2004-02-10 18:18:00) [6]
В строчке SELECT MIN(id) mn --,f1,f2 --,f1,f2- комментарий, не нужен.
panov (2004-02-10 18:17:00) [7]
Пусть T1 имеет поля Id, f1,f2, где сравнение на дубль идет по полям f1, f2 .
SELECT *
FROM
T1 a
WHERE
a.id NOT IN
(
SELECT MIN(id) mn --,f1,f2
FROM
(
SELECT a.id,a.f1,a.f2
FROM
T1 a,
(
SELECT f1,f2,cnt
FROM
(
SELECT f1,f2,COUNT(*) cnt FROM T1 GROUP BY f1,f2
) b
WHERE cnt>1
) b
WHERE a.f1=b.f1 AND a.f2=b.f2
) b
GROUP BY f1,f2
)
AND
a.id in
(
SELECT a.id
FROM
T1 a,
(
SELECT f1,f2,cnt
FROM
(
SELECT f1,f2,COUNT(*) cnt FROM T1 GROUP BY f1,f2
) b
WHERE cnt>1
) b
WHERE a.f1=b.f1 AND a.f2=b.f2
)
здесь несколько лишних алиасов, так как отлаживалось в MSSQL, но будет работать и в Oracle.
Если нет уникального Id, то вместо него можно использовать RowId.
В самом верхнем селекте зменить SELECT НА DELETE, естественно
Johnmen (2004-02-10 17:56:00) [8]
>Vlad ©
К сожалению ничем конкретно не помогу...
Но общие соображения : в ХП просто делаем обход по селекту в цикле и для каждой записи отдельный делете. Т.е. "развязываем" один запрос на два... Ну и прагму "подпихнуть" :)
Fay (2004-02-10 17:51:00) [9]
Уникальность достигается другим способом. Для этого есть UNIQUE.
Vlad (2004-02-10 16:22:00) [10]
> [3] Johnmen © (10.02.04 14:25)
Попробовал указать прагму, но при таком запросе в ХП Оракл вобще откатывает транзакцию с ошибкой
DenK_vrtz (2004-02-10 16:01:00) [11]
>Vlad ©
Если копать в сторону "мутации" (Johnmen © (10.02.04 13:54) [1]), то еще вариант к Johnmen © (10.02.04 14:25) [3] это
view и instead of триггер на удаление для этого вью
Попробуй :)
sniknik (2004-02-10 14:46:00) [12]
а вроде в Oracle есть чтото вроде номера записи(?) может его както задействовать?
а вообще можно проще (по моему) и в большем количестве SQL серверов работать будет. хотя и за большее количество итераций.
select * into NewTable from (select distinct * from OldTable)
дальше надо удалить старую и переименовать новую.
Johnmen (2004-02-10 14:25:00) [13]
>Vlad © (10.02.04 13:58)
Уже основательно это хозяйство подзабыл...:)
Думаю, что надо смотреть в эту сторону:
1. ХП
2. PRAGMA AUTONOMOUS_TRANSACTION
Vlad (2004-02-10 13:58:00) [14]
> Johnmen © (10.02.04 13:54) [1]
> скорее всего, надо отключить "мутацию".
Спасибо. А каким образом это делается ?
Johnmen (2004-02-10 13:54:00) [15]
Я думаю, что дело в логике работы сервера.
Для ИБ - идет делетом по записям и каждую, удовл-ую условию, удаляет, поэтому для следующей записи селект вернет уже другое значение.
А для Оракла несколько иначе. Поскольку селект делается из модифицируемой таблицы, то, скорее всего, надо отключить "мутацию".