Комната: запрос DAO, который удаляет дубликаты, заданные несколькими столбцами в качестве критерия - PullRequest
0 голосов
/ 13 декабря 2018

Предполагается, что мы используем Room и имеем DAO , который реализует наше взаимодействие с таблицей SQLite.Есть ли способ построить запрос, который может идентифицировать один или несколько столбцов, которые имеют одинаковое значение, т.е. считаются дубликатами, и удалять их?

Например, у нас есть эта таблица:

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

В этом случае мы считаем name и lastname критериями для определения идентичности строки.Поэтому, если name и lastname одинаковы, мы хотим сохранить только одну строку, поскольку существуют дубликаты.Здесь строки 1, 2 повторяются.

Более или менее это , но я не могу использовать, например USING table, я получаю ошибки.И я также не уверен, как использовать несколько столбцов в качестве критерия.

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

Попробуйте создать следующее Query в интерфейсе DAO:

@Dao
public interface MyDaoTest {

    ...

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

    ...
}

Этот запрос удалит все строки, в которых дублируются name и lastName.

Например, если у нас есть следующая таблица, мы можем видеть, что строки с идентификаторами 1, 2 и 6 являются дубликатами, то же самое с строками с идентификаторами 3 и 4,тогда как строка с 5 не имеет дубликатов.

original table with duplicates

Этот запрос группирует строки по name и lastName, оставляя толькоодин с минимальным идентификатором.Делая это, мы гарантируем, что мы получим только одну строку на каждый набор повторяющихся строк (с минимальным идентификатором)

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

result of select min

Наконец, если мы удалим все строки, идентификаторы которых не содержатся в результате этого внутреннего запроса, мы избавимся от дубликатов.

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

result

0 голосов
/ 14 декабря 2018

Вы можете использовать Составной первичный ключ

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

Поэтому, когда вы вставляете новое значение, вы можете переопределить или просто проигнорировать, если name и lastname совпадают.

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

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