Reputation: 1590
I am looking to return the full information on duplicate records from my table.
I am currently using the following:
DB::table($entity['table'])
->select('*')
->groupBy($entity['columns'])
->havingRaw('COUNT(*) > 1')
->get();
Which is great, it returns the duplicate records, however, this only returns one of the records I need to return all the duplicates so that I can greet the user with a choice on which one to delete or keep.
How can I modify the above query to accomplish that?
Upvotes: 2
Views: 5488
Reputation: 117
You can accomplish this by using whereIn and a function to query the same table that you are working with.
Let say you have a scenario where you want to look for duplicate records containing the same last name in the user table.
Database Table - User
--- user_id --- first_name --- last_name --- email --- 1 Dan Smith [email protected] 2 Jim Jones [email protected] 3 Amy Grant [email protected] 4 Bob Brown [email protected] 5 Sue Davis [email protected] 6 Leo Grant [email protected] 7 Ann Grant [email protected]
Then you can use the following code;
$duplicates = DB::table('user')
->select('user_id', 'last_name')
->whereIn('user_id', function ($q){
$q->select('user_id')
->from('user')
->groupBy('last_name')
->havingRaw('COUNT(*) > 1');
})->get();
Which will return the following;
--- user_id --- last_name 3 Grant 6 Grant 7 Grant
Upvotes: 0
Reputation: 26477
Joining against the same table will allow you to retrieve the duplicate records without just getting a single version of it (caused by your groupBy in your question)
$entity['columns'] = ['username', 'surname'];
$groupBy = implode(',', $entity['columns']);
$subQuery = DB::table('list')
->select('*')
->groupBy($groupBy)
->havingRaw('(count(id) > 1))');
$result = DB::table('list')
->select('*')
->join(
DB::raw("({$subQuery->toSql()}) dup"), function($join) use ($entity) {
foreach ($entity['columns'] as $column) {
$join->on('list.'.$column, '=', 'dup.'.$column);
}
})
->toSql();
// or ->get(); obviously
dd($result);
Upvotes: 1
Reputation: 34231
You need to join back to the table in $entity['table'] on the columns in the $entity['columns'] to get the duplicates.
Also, the select('*') is not really a good idea even if you are using mysql. This is against the sql standard and works in mysql only if it is configured in a certain way. If the configuration changes or you migrate your app to a mysql server with different configuration on sql modes, your query will fail.
I would use $entity['columns'] in the select list as well.
In sql the query should look like as follows:
select table.* from table inner join
(select field1, field2 from table t
group by field1, field2
having count(*)>1) t1
on table.field1=t1.field1 and table.field2=t1.field2
Upvotes: 0