Reputation: 826
Assuming we are using Room and have a DAO which implements our interactions with an SQLite table. Is there a way to construct a query that can identify one or more columns that have the same value, i.e. considered duplicates, and remove them?
E.g. we have this table:
primKey | name | lastname | phone |
1 foo bar 222
2 foo bar 333
3 oof rab 123
In this case, we consider name
and lastname
to be the criteria to determine if the row is identical. So if name
and lastname
is the same we want to keep only one row, as there exist duplicates. Here row 1, 2 are duplicate.
More or less this but I cannot use for example USING table
, I am getting errors. And I am also not sure how to use multiple columns as criteria.
Upvotes: 2
Views: 2591
Reputation: 6607
Try creating the following Query
in your DAO
interface:
@Dao
public interface MyDaoTest {
...
@Query("DELETE FROM test
WHERE id NOT IN (SELECT MIN(id) FROM test GROUP BY name, lastName)")
void deleteDuplicates();
...
}
That query, will delete all the rows in which the name
and lastName
are duplicated.
For example, if we have the following table, we can see that the rows with id 1
, 2
and 6
are duplicates, the same with the rows with id 3
and 4
, whereas the row with 5
has no duplicates.
This query will group the rows by name
and lastName
, leaving only the one with the minimum ID. By doing that, we make sure we get only one row per every set of duplicate rows (the one with the minimum ID)
SELECT MIN(id)
FROM test
GROUP BY name, lastName;
Finally, if we delete all the the rows whose IDs are not contained in the result of that internal query, we will get rid of the duplicates.
DELETE
FROM test
WHERE id NOT IN
(SELECT MIN(id)
FROM test
GROUP BY name, lastName);
Upvotes: 3
Reputation: 6882
You can use Composite Primary Key
@Entity(primaryKeys = ["name", "lastname"])
data class User(
// you can ignore your primaryKey field
val name: String,
val lastname: String,
val phone: Long
)
So whenever you insert a new value you can override or just ignore if name
and lastname
are the same.
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertReplace(user: User)
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertIgnore(user: User)
Upvotes: 1