туча дублей, дубли разные могут содержать дополнительные полезные поля.
Нужно найти эти дубли, выбрать из них самый полезный, остальные удалить. Сделал команду
public function handle()
{
$this->info('Проверяем дубликаты в ...');
// Поиск дубликатов с учетом регистра
$duplicates = DB::table('point')
->select(DB::raw('BINARY(name) as name'), 'addres', DB::raw('COUNT(*) as count'))
->groupBy(DB::raw('BINARY(name)'), 'addres')
->havingRaw('COUNT(*) > 1')
->get();
$progressBar = new ProgressBar($this->output, count($duplicates));
$progressBar->setFormat('%current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% Осталось времени: %remaining:6s% Использование памяти: %memory:6s%');
$progressBar->start();
$deletedCount = 0;
foreach ($duplicates as $duplicate) {
// Получение всех записей-дубликатов
$records = DB::table('point')
->where(DB::raw('BINARY(name)'), $duplicate->name)
->where('addres', $duplicate->addres)
->get();
$minFields = PHP_INT_MAX;
$recordToDelete = null;
foreach ($records as $record) {
// Подсчет количества заполненных полей
$filledFields = count(array_filter((array)$record, function ($value) {
return !is_null($value) && $value !== '';
}));
// Выбор записи с наименьшим количеством заполненных полей
if ($filledFields < $minFields) {
$minFields = $filledFields;
$recordToDelete = $record;
}
}
if ($recordToDelete) {
// Удаление записи без подтверждения
DB::table('point')
->where('id', $recordToDelete->id)
->delete();
$deletedCount++;
}
$progressBar->advance();
}
$progressBar->finish();
$this->line('');
$this->info("Удалено $deletedCount дубликатов.");
}
Обрами в код, а то паршиво ясно)) На первый взгляд можно запросить все дубликаты сразу сгруппировав уже коллекцию. А запрашивать используя группировку с хэвинг как подзапрос. select * from point where id in (select id from point group by binary(name),addres having count(*) > 1)
Мне нужно проверить каждый дубль отдельно, так как внутри может быть несколько записей одинаковых
Обсуждают сегодня