如何删除 Laravel 中具有相同列值的重复行?
How do I remove duplicate rows with same column values in Laravel?
我正在尝试在 Laravel 中执行 artisan 命令以删除所有具有相同地址的场所并保留 ID 编号最小的场所(因此首先创建)。
为此我需要检查 3 个字段:'street'、'house_number'、'house_number_addition'
这是我的进度:
$venues = Venue::select('street', 'house_number', 'house_number_addition', DB::raw('COUNT(*) as count'))
->groupBy('street', 'house_number', 'house_number_addition')
->having('count', '>', 1)
->get();
foreach ($venues as $venue) {
$this->comment("Removing venue: {$venue->street} {$venue->house_number} {$venue->house_number_addition}");
$venue->delete();
}
只有删除不起作用,但也没有报错。
要删除项目,Eloquent 需要知道它的 ID。如果您确定模型的 ID 已被查询,您可以毫无问题地调用 delete()
。
然而,在您的查询中,这将不起作用,因为您有一个 GROUP_BY
语句,因此 SQL 不允许您 select id
列 (see here).
这里最简单的解决方案是利用 Eloquent 的 Collection
class 映射模型,例如:
$uniqueAddresses = [];
Venue::all()
->filter(function(Venue $venue) use (&$uniqueAddresses) {
$address = sprintf("%s.%s.%s",
$venue->street,
$venue->house_number,
$venue->house_number_addition);
if (in_array($address, $uniqueAddresses)) {
// address is a duplicate
return $venue;
}
$uniqueAddresses[] = $address;
})->map(function(Venue $venue) {
$venue->delete();
});
或者,让您的删除查询更高效(取决于您的数据集有多大):
$uniqueAddresses = [];
$duplicates = [];
Venue::all()
->map(function(Venue $venue) use (&$uniqueAddresses, &$duplicates) {
$address = sprintf("%s.%s.%s",
$venue->street,
$venue->house_number,
$venue->house_number_addition);
if (in_array($address, $uniqueAddresses)) {
// address is a duplicate
$duplicates[] = $venue->id;
} else {
$uniqueAddresses[] = $address;
}
});
DB::table('venues')->whereIn('id', $duplicates)->delete();
Note: the last one will permanently delete your models; it doesn't work with Eloquent's SoftDeletes
functionality.
当然,您也可以编写一个原始查询来完成这一切。
我正在尝试在 Laravel 中执行 artisan 命令以删除所有具有相同地址的场所并保留 ID 编号最小的场所(因此首先创建)。
为此我需要检查 3 个字段:'street'、'house_number'、'house_number_addition'
这是我的进度:
$venues = Venue::select('street', 'house_number', 'house_number_addition', DB::raw('COUNT(*) as count'))
->groupBy('street', 'house_number', 'house_number_addition')
->having('count', '>', 1)
->get();
foreach ($venues as $venue) {
$this->comment("Removing venue: {$venue->street} {$venue->house_number} {$venue->house_number_addition}");
$venue->delete();
}
只有删除不起作用,但也没有报错。
要删除项目,Eloquent 需要知道它的 ID。如果您确定模型的 ID 已被查询,您可以毫无问题地调用 delete()
。
然而,在您的查询中,这将不起作用,因为您有一个 GROUP_BY
语句,因此 SQL 不允许您 select id
列 (see here).
这里最简单的解决方案是利用 Eloquent 的 Collection
class 映射模型,例如:
$uniqueAddresses = [];
Venue::all()
->filter(function(Venue $venue) use (&$uniqueAddresses) {
$address = sprintf("%s.%s.%s",
$venue->street,
$venue->house_number,
$venue->house_number_addition);
if (in_array($address, $uniqueAddresses)) {
// address is a duplicate
return $venue;
}
$uniqueAddresses[] = $address;
})->map(function(Venue $venue) {
$venue->delete();
});
或者,让您的删除查询更高效(取决于您的数据集有多大):
$uniqueAddresses = [];
$duplicates = [];
Venue::all()
->map(function(Venue $venue) use (&$uniqueAddresses, &$duplicates) {
$address = sprintf("%s.%s.%s",
$venue->street,
$venue->house_number,
$venue->house_number_addition);
if (in_array($address, $uniqueAddresses)) {
// address is a duplicate
$duplicates[] = $venue->id;
} else {
$uniqueAddresses[] = $address;
}
});
DB::table('venues')->whereIn('id', $duplicates)->delete();
Note: the last one will permanently delete your models; it doesn't work with Eloquent's
SoftDeletes
functionality.
当然,您也可以编写一个原始查询来完成这一切。