Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Kolek54
Member

Откуда:
Сообщений: 4
Дано:
Таблица товаров Product (ProductId, oem, name, ....)
Таблица продаж SaleItem (SaleItemId, ProductId,...)
Таблица заказов OrderItem (OrderItemId, ProductId, ...)

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


Запрос на удаление дублей из таблицы Product я написал
delete from product
where productid >
(select min(productid)
From product as p1
Where product.oem=p1.oem)

Но перед удалением, необходимо изменить записи в таблицах SaleItem, OrderItem, подставив минимальный productid из дублей.
Просьба помочь с запросом.
Заранее спасибо.
28 авг 10, 08:06    [9342127]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
Kolek54,
так как модифицируется несколько таблиц, то первое вам надо создать временную табличку
типа #mapTable (OldProductId int , NewProductID ) , а затем проапдейтить соответсвующие таблички
минимальный номер продукта


  SELECT TOP 1 WITH TIES 
  ProductId --,oem,name
  FROM Product 
 ORDER BY ROW_NUMBER  ( PARTITION BY  oem, name  ORDER BY ProductID ASC )

28 авг 10, 08:43    [9342137]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
declare @p table
(
  pid int
  ,oem varchar(12)
  ,name varchar(12)
)


insert @p ( pid,oem,name)
select 1,'a','a' union
select 2,'a','a' union
select 3,'a','a' union  
select 4,'b','b' union
select 5,'b','b' union  
select 6,'c','c' union
select 7,'d','d' 


SELECT 
p.pid OldPID
,T.pid NewPID
FROM @p p
INNER JOIN (
  SELECT TOP 1 WITH TIES
  p2.pid
  ,p2.oem
  ,p2.name
  FROM @p p2
  ORDER BY ROW_NUMBER() OVER ( PARTITION BY oem,name ORDER BY pid ASC )
) T ON (T.name = p.name and T.oem = p.oem and p.pid <> T.pid)
28 авг 10, 09:02    [9342146]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Ken@t
Member

Откуда: 大地
Сообщений: 3265
Ken@t,

ps сделайте UNIQUE на OEM и name
и не всё так радужно будет SaleItem ,OrderItem - задвоение не начнётся

вообще , судя по всему , с струтурами таблиц - полный аут.
28 авг 10, 09:06    [9342147]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Kolek54
Member

Откуда:
Сообщений: 4
Спасибо!!
Буду пробовать.
28 авг 10, 09:41    [9342162]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Kolek54
Member

Откуда:
Сообщений: 4
Ken@t,


Ругается на row_number, partition, забыл сказать, у меня MS SQL 2000.
28 авг 10, 11:10    [9342262]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
iljy
Member

Откуда:
Сообщений: 8711
Kolek54,

как-то так
begin tran
-- создаем соответствие номеров товаров
if object_id('tempdb..#temp_ids') is not null drop table #temp_ids
create table #temp_ids (id_old int primary key, id_new int)
insert #temp_ids
select t1.ProductId, t2.min_id
from Product t1 join
(
	select oem, name, min(ProductId) min_id
	from Product
	group by oem, name
) t2
	on t1.oem = t2.oem and t1.name = t2.name
-- Меняем связанные таблицы
update s
set ProductId = t.id_new
from SaleItem s join #temp_ids t on s.ProductId = t.id_old

update o
set ProductId = t.id_new
from OrderItem o join #temp_ids t on o.ProductId = t.id_old
-- Чистим таблицу продуктов.
delete Product
where ProductId not in (select id_new from #temp_ids)

-- Проверяете, что все как надо, потом
-- drop table #temp_ids
-- commit
28 авг 10, 11:45    [9342330]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Kolek54
Member

Откуда:
Сообщений: 4
iljy
Kolek54,

как-то так
begin tran
-- создаем соответствие номеров товаров
if object_id('tempdb..#temp_ids') is not null drop table #temp_ids
create table #temp_ids (id_old int primary key, id_new int)
insert #temp_ids
select t1.ProductId, t2.min_id
from Product t1 join
(
	select oem, name, min(ProductId) min_id
	from Product
	group by oem, name
) t2
	on t1.oem = t2.oem and t1.name = t2.name
-- Меняем связанные таблицы
update s
set ProductId = t.id_new
from SaleItem s join #temp_ids t on s.ProductId = t.id_old

update o
set ProductId = t.id_new
from OrderItem o join #temp_ids t on o.ProductId = t.id_old
-- Чистим таблицу продуктов.
delete Product
where ProductId not in (select id_new from #temp_ids)

-- Проверяете, что все как надо, потом
-- drop table #temp_ids
-- commit


Спасибо огромно!! Все получилось.
28 авг 10, 13:05    [9342489]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Osho
Member

Откуда:
Сообщений: 21
Та же самая проблема, необходимо удалить дубликаты компаний, к которым привязано несколько таблиц с последующим апдейтом последних, но в во временной таблице:
select t1.Id, t2.min_id
from Companies t1 right join
(
	select Name, Inn, Kpp, min(Id) min_id
	from Companies
	group by Name, Inn, Kpp
) t2 on t1.Name = t2.Name and t1.Inn = t2.Inn and t1.Kpp = t2.Kpp  
order by min_id


отсутствуют id дубликатов, есть компании которые ни разу не повторяются.
Если делать просто запрос:

select Name, Inn, Kpp, min(Id) min_id
	from Companies
	group by Name, Inn, Kpp
	order by min_id


то в результирующей выборке присутствуют нужные компании.

В чем может быть причина такого поведения? Помогите, пожалуйста, написать правильно. Версия Microsoft SQL Server 2012
21 апр 14, 12:25    [15910100]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Glory
Member

Откуда:
Сообщений: 104751
Osho
В чем может быть причина такого поведения?

Такое поведение связно с тем, что данный запрос вовсе и не должен выводить дубликаты.
Этот запрос из всех дубликатов выбирает тот, который останется.
21 апр 14, 12:32    [15910131]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Osho
Member

Откуда:
Сообщений: 21
Glory
Этот запрос из всех дубликатов выбирает тот, который останется.

В том то и дело что их нет
21 апр 14, 12:40    [15910171]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Glory
Member

Откуда:
Сообщений: 104751
Osho
Glory
Этот запрос из всех дубликатов выбирает тот, который останется.

В том то и дело что их нет

Если у вас нет дубликатов, то почему вы пишите "Та же самая проблема, необходимо удалить дубликаты компаний" ?
21 апр 14, 12:41    [15910177]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Osho
Member

Откуда:
Сообщений: 21
нет того, который останется
21 апр 14, 12:41    [15910181]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Glory
Member

Откуда:
Сообщений: 104751
Osho
нет того, который останется

Значит у вас нет данных в таблице
21 апр 14, 12:42    [15910184]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Osho
Member

Откуда:
Сообщений: 21
Glory
Значит у вас нет данных в таблице


Они есть и это не обсуждается, обсуждается то, как написать правильно запрос, чтобы он выдал то, что надо.
21 апр 14, 12:45    [15910203]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Osho
Member

Откуда:
Сообщений: 21
А фишка в том, что Kpp может принимать значения Null:

select t1.Id, t2.min_id
from Companies t1 inner join
(
	select Name, Inn, Kpp, min(Id) min_id
	from Companies
	group by Name, Inn, Kpp
) t2 on t1.Name = t2.Name and t1.Inn = t2.Inn and (t1.Kpp = t2.Kpp or (t1.Kpp IS NULL and t2.Kpp IS NULL))
order by min_id


Вот так все работает!
21 апр 14, 12:48    [15910225]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Glory
Member

Откуда:
Сообщений: 104751
Osho
Они есть и это не обсуждается,

Офигительное утверждение
Если запрос
select Name, Inn, Kpp, min(Id) min_id
from Companies
group by Name, Inn, Kpp
ничего не вернул, то данных в таблице НЕТ. И это не обсуждается.

Если вернул, то он вернул не список дубликатов, а список тех записей, которые останутся после удаления дубликатов
21 апр 14, 12:49    [15910231]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Osho
Member

Откуда:
Сообщений: 21
Glory
Офигительное утверждение
Если запрос
select Name, Inn, Kpp, min(Id) min_id
from Companies
group by Name, Inn, Kpp

ничего не вернул, то данных в таблице НЕТ. И это не обсуждается.


Перед тем как писать, читайте, пожалуйста, внимательно, что я написал в первом своем посте данной темы.
Osho
то в результирующей выборке присутствуют нужные компании.
21 апр 14, 12:57    [15910287]     Ответить | Цитировать Сообщить модератору
 Re: Удаление дубликатов, с предварительной обработкой связанных таблиц  [new]
Glory
Member

Откуда:
Сообщений: 104751
Osho
Перед тем как писать, читайте, пожалуйста, внимательно, что я написал в первом своем посте данной темы.

Может это вам нужно яснее облекать ваши мысли в слова и предложения ?
21 апр 14, 12:58    [15910303]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить