Room:DAO 查询,删除给定多列作为条件的重复项

Room: DAO query that removes duplicates given multiple columns as criteria

假设我们使用 Room and have a DAO 来实现我们与 SQLite table 的交互。有没有一种方法可以构建一个查询,该查询可以识别一个或多个具有相同值的列,即被认为是重复的列,并将它们删除?

例如我们有这个 table:

primKey | name | lastname | phone |
 1        foo      bar       222
 2        foo      bar       333  
 3        oof      rab       123 

在这种情况下,我们将namelastname作为判断行是否相同的标准。因此,如果 namelastname 相同,我们只想保留一行,因为存在重复项。这里第 1、2 行重复。

More or less this 但我无法使用 USING table,我收到错误消息。而且我也不确定如何使用多列作为条件。

您可以使用复合主键

@Entity(primaryKeys = ["name", "lastname"])
data class User(
    // you can ignore your primaryKey field
    val name: String,
    val lastname: String,
    val phone: Long
)

因此,无论何时插入新值,如果 namelastname 相同,您都可以覆盖或忽略。

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertReplace(user: User)

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertIgnore(user: User)

尝试在您的 DAO 界面中创建以下 Query

@Dao
public interface MyDaoTest {

    ...

    @Query("DELETE FROM test
            WHERE id NOT IN (SELECT MIN(id) FROM test GROUP BY name, lastName)")
    void deleteDuplicates();

    ...
}

该查询将删除 namelastName 重复的所有行。

例如,如果我们有下面的table,我们可以看到id为126的行是重复的,同理ID 为 34 的行,而 ID 为 5 的行没有重复项。

此查询将按 namelastName 对行进行分组,仅保留具有最小 ID 的行。通过这样做,我们确保每组重复行只得到一行(具有最小 ID 的行)

SELECT MIN(id)
FROM test
GROUP BY name, lastName;

最后,如果我们删除其 ID 不包含在该内部查询结果中的所有行,我们将删除重复项。

DELETE
FROM test
WHERE id NOT IN
(SELECT MIN(id)
FROM test
GROUP BY name, lastName);