powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Удаление строки по результатам сравнения с предыдущей.
19 сообщений из 19, страница 1 из 1
Удаление строки по результатам сравнения с предыдущей.
    #39901084
genri200
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте! Помогите пожалуйста с решением нетривиальной пока что для меня такой задачи.
Есть таблица вида
ID Family Name1ПоповИван2СидоровЮрий3СидоровЮрий4ПетровВасилий5ИвановСергей6ИвановСергей7ПоповЮрий
Нужно удалить строки, где фамилия и имя совпадают с предыдущей строкой, чтобы таблица стала такой:

ID Family Name1ПоповИван4ПетровВасилий7ПоповЮрий

Записей примерно 50 тысяч, я думаю без оператора While не обойтись. Заранее благодарю.
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901087
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200,

Код: sql
1.
2.
3.
4.
;with cte as (
	select *, row_number()over(order by ID) as rn from [Есть таблица вида])

delete t1 from cte t1 where exists(select 1 from cte t2 where t1.Family=t2.Family and t1.Name=t2.Name and t1.rn in (t2.rn-1,t2.rn+1))
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901093
genri200
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо огромное, но забыл добавить, что версия базы данных довольно древняя - Microsoft SQL 2008 R2. Инструкция OVER() поддерживается насколько я понимаю от SQL 2012
Можно ли выполнить эту задачу без OVER ?
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901098
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200
Инструкция OVER() поддерживается насколько я понимаю от SQL 2012
брэхня ! :)
genri200
Можно ли выполнить эту задачу без OVER

нуу, как-то жили люди и до исторического материализма OVER :)
... не очень, конечно, но для 50к записей должно быть "нестрашно"
Код: sql
1.
2.
3.
4.
;with cte as (
	select *, (select count(*) from [Есть таблица вида] t2 where t2.ID<=t1.ID) as rn from [Есть таблица вида] t1)

delete t1 from cte t1 where exists(select 1 from cte t2 where t1.Family=t2.Family and t1.Name=t2.Name and t1.rn in (t2.rn-1,t2.rn+1))
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901100
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
DELETE 
FROM mytable
WHERE EXISTS ( SELECT NULL
               FROM mytable t
               WHERE mytable.id     > t.id
                 AND mytable.Family = t.Family
                 AND mytable.Name   = t.Name )
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901135
genri200
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
court, Akina - спасибо!
Akina, не совсем понятно из вашего примера, откуда берется таблица t :( Это дубль mytable ?
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901203
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200
Akina, не совсем понятно из вашего примера, откуда берется таблица t :( Это дубль mytable ?
Называется "Алиас" (см. справку).
Алиасы позволяют более кратко обзывать таблицы, и использовать в запросе одну таблицу несколько раз.

Я бы и первое упоминание таблицы сделал алиасом. Для понятности:
Код: sql
1.
2.
3.
4.
5.
6.
7.
DELETE m
FROM mytable as m
WHERE EXISTS ( SELECT NULL
               FROM mytable as t
               WHERE m.id     > t.id
                 AND m.Family = t.Family
                 AND m.Name   = t.Name )
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901222
genri200
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alexeyvg,

Спасибо, уже разобрался. Один нюанс остается, если будет таблица вида
ID Family Name1ПоповИван2СидоровЮрий3СидоровЮрий4ПетровВасилий5ИвановСергей6ИвановСергей7ПоповЮрий8ИвановСергей
То вышеуказанный код как я понимаю удалит всех Ивановых, но 8 строку надо оставить, так как в предыдущей (седьмой) строке не Иванов, а Попов.
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901229
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200
То вышеуказанный код как я понимаю удалит всех Ивановых, но 8 строку надо оставить, так как в предыдущей (седьмой) строке не Иванов, а Попов.

проверил бы, уже ...

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
declare @t table (ID int,	Family varchar(50),	Name varchar(50))
insert into @t values
(1,	'Попов',	'Иван'),
(2,	'Сидоров',	'Юрий'),
(3,	'Сидоров',	'Юрий'),
(4,	'Петров',	'Василий'),
(5,	'Иванов',	'Сергей'),
(6,	'Иванов',	'Сергей'),
(7,	'Попов',	'Юрий'),
(8,	'Иванов',	'Сергей')


;with cte as (
	select *, row_number()over(order by ID) as rn from @t)

delete t1 from cte t1 where exists(select 1 from cte t2 where t1.Family=t2.Family and t1.Name=t2.Name and t1.rn in (t2.rn-1,t2.rn+1))

select * from @t 


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
(8 rows affected)

(4 rows affected)
ID          Family                                             Name
----------- -------------------------------------------------- --------------------------------------------------
1           Попов                                              Иван
4           Петров                                             Василий
7           Попов                                              Юрий
8           Иванов                                             Сергей

(4 rows affected)
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901232
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
declare @t table (ID int, Family varchar(30), Name varchar(30));

insert into @t
values
(1, 'Попов', 'Иван'),
(2, 'Сидоров', 'Юрий'),
(3, 'Сидоров', 'Юрий'),
(4, 'Петров', 'Василий'),
(5, 'Иванов', 'Сергей'),
(6, 'Иванов', 'Сергей'),
(7, 'Попов', 'Юрий'),
(8, 'Иванов', 'Сергей');

with a as
(
 select
  row_number() over (order by ID) - row_number() over (partition by Family, Name order by ID) as g
 from
  @t
),
b as
(
 select count(*) over (partition by g) as c from a
)
delete from b where c > 1;

select * from @t;
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901243
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200
вышеуказанный код как я понимаю удалит всех Ивановых
Да.
genri200
8 строку надо оставить, так как в предыдущей (седьмой) строке не Иванов, а Попов.
Замените
Код: sql
1.
WHERE m.id > t.id

на
Код: sql
1.
WHERE m.id = t.id + 1


Если же в значении id имеются "дырки" - пронумеруйте записи без дыр в CTE, a потом удаляйте. Или в подзапросе сделайте ещё один коррелированный NOT EXISTS.
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901331
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
declare @t table (ID int, Family varchar(30), Name varchar(30));

insert into @t
values
(1, 'Попов', 'Иван'),
(2, 'Сидоров', 'Юрий'),
(3, 'Сидоров', 'Юрий'),
(4, 'Петров', 'Василий'),
(5, 'Иванов', 'Сергей'),
(6, 'Иванов', 'Сергей'),
(7, 'Попов', 'Юрий'),
(8, 'Иванов', 'Сергей');

with a as
(
 select
  ID
  , Family, FamilyLag= LAG(Family, 1, NULL) OVER (ORDER BY ID)
  , Name, NameLag= LAG(Name, 1, NULL) OVER (ORDER BY ID)
 from
  @t
)
DELETE FROM a
WHERE Family = FamilyLag AND Name = NameLag;

select * from @t;
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901354
genri200
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Благодарю, пока вариант court и invm сработал корректнее, другой вариант оставляет одну запись из дублей.
court, такой вопрос, что нужно добавить в ваш код, чтобы дополнительно проверить еще на одно условие при удалении, например в таблице

ID Family Name Cond1ПоповИван12СидоровЮрий03СидоровЮрий04ПетровВасилий15ИвановСергей16ИвановСергей17ПоповЮрий0
удалить строки там, где Cond=1 и не трогать, где Cond=0.
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901366
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200
удалить строки там, где Cond=1 и не трогать, где Cond=0.
Добавить "WHERE ... AND Cond=1", вероятно... если имеется в виду поле в удаляемой записи, и пофиг на другие копии.
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901417
genri200
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо всем, в итоге лучше всего подошел код от court с дополнением условия:

Код: sql
1.
2.
3.
with cte as (
	select *, row_number()over(order by ID) as rn from @t)
delete t1 from cte t1 where exists(select 1 from cte t2 where t1.Family=t2.Family and t1.Name=t2.Name and t1.rn in (t2.rn-1,t2.rn+1)) AND Cond=1
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901485
genri200
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вдогонку еще один вопрос по удалению, есть две таблицы:
ID Family Name1ПоповИван3СидоровЮрий4ПетровВасилий6ИвановСергей7ПоповЮрий
и
ID Family Name2СидоровЮрий4ПетровВасилий5ИвановСергей6ИвановСергей
Нужно удалить строки в обеих таблицах, если хотя бы в одной из таблиц нет ID, которое есть в другой, то есть на выходе должны получиться такие таблицы

ID Family Name4ПетровВасилий6ИвановСергей
и
ID Family Name4ПетровВасилий6ИвановСергей

ID 4 и 6 присутствуют в обеих таблицах, эти строки не трогаем, остальные удаляем.
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901627
PizzaPizza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200

Нужно удалить строки в обеих таблицах, если хотя бы в одной из таблиц нет ID, которое есть в другой


надо ж так сформулировать, что надо оставить только те записи, которые присутствуют в обоих таблицах.
От таких формулировок и запросы соответствующие получаются.
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901633
Фотография crutchmaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200
совпадают с предыдущей строкой

На будущее. В РСУБД нет такого понятия как предыдущая или следующая строка. Порядок, как правило, нигде не гарантируется. Даже в случае с id надо всё обеспечивать руками, чтобы такая логика не поломалась после очередной "заливки".
...
Рейтинг: 0 / 0
Удаление строки по результатам сравнения с предыдущей.
    #39901745
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
genri200
ID 4 и 6 присутствуют в обеих таблицах, эти строки не трогаем, остальные удаляем.

Код: sql
1.
2.
3.
delete t1
from t1 left join t2 on t1.id=t2.id
where t2.id is null


и второй запрос точно такой же с заменой t1 на t2 и наоборот
...
Рейтинг: 0 / 0
19 сообщений из 19, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Удаление строки по результатам сравнения с предыдущей.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]