I am using Room as ORM. I want to get array of some objects from it with a specific order. My code looks like this:
#Query("SELECT * FROM `group` WHERE id IN (:ids) ORDER BY id in (:ids)")
But "order by" not works. I don't want just to sort it by field "id". I want to sort it by id that correlate with array "ids". I mean:
I have array of Integer ids = arrayOf(16,12,18,3) and i use it in query above. And on the output i want to have array of some object(say group). The output array will looks like this
ListOf(Group(id:16, name: "someName"),
Group(id: 12, name: "someAnotherName",
Group(id: 18, name: "name"),
Group(id: 3, name: "another"))
So you where quite close. Try using
#Query("SELECT * FROM `group` WHERE id IN (:ids) ORDER BY id")
That should work for you. Im not sure on the group
You using wrong way, ORDER BY id in (:ids) is incorrect
it should be
#Query("SELECT * FROM `group` WHERE id IN (:ids) ORDER BY id")
To retrieve data from database in the order you want is impossible, as the database don't know about current indexes in the array for ids. Actually it's possible, but you have to provide this information in a query or store it beforehand in a table.
What you actually want, is to get corresponding group information by some ids, so
retrieve group data without ordering
#Query("SELECT * FROM group WHERE id IN (:ids)")
fun getGroupsById(): List<Group>`
store the result into a map
val idToGroups = mapOf<Long, Group>()
for (group in getGroupsById()) {
idToGroups[group.id] = group
}
then while iterating over initial ids array, get corresponding groups by id
for (id in ids) {
// here group is related to each position in the array
group = idToGroups[id]
println("Id: ${id}, Name: ${group.name}")
}
Related
I am trying to sort my data by ascending and descending order using room database. So I need to pass those parameter to the DAO.
This is my code:
#Query("SELECT * FROM DEVICES_TABLE ORDER BY :sortQuery")
fun sortDatabase(sortQuery: String): Flow<List<DeviceData>>
But when I pass title DESC as sortquery (title is column name), the query becomes:
SELECT *
FROM DEVICES_TABLE
ORDER BY 'title ASC'
I need to remove those single quotes from query for achieving the results. I need to sort with title, price, type etc. both ascending and descending. How can I do that?
Get the list of EXISTS flags, by the list of IDs from the database using Room.
I need to get a list of the same size, in which if the element is not in the database, false will be stored, and if there is, true
#Query("SELECT EXISTS (SELECT * FROM FavoriteCharacter WHERE id IN (:ids))")
fun existsRx(ids: List<Int>): List<Boolean>
I tried to do it this way, however, I get a list of one element.
The SQLite query you want is probably something like this:
SELECT id, id IN (:ids) AS id_has
FROM FavoriteCharacter
This would return every id in your table, along with a boolean value as to whether or not that id value is also contained in the input list of integers.
I'm not a Room guru, so I don't know exactly how your method signature would need to change.
I have a program where data is stored in a local database using Room, and I receive data through RxJava2. In Provider, the database created a method that takes one parameter - an identifier, by which it sends a request and receives certain data that corresponds to the identifier. But I want to pass as a parameter not one identifier, but an array of identifiers and get an array as well, but I don't know how. I don’t want to implement it through for, because I think there is a better solution, but I couldn’t find it. My code is shown below.
...
userDatabase.userDao().getById(id)
.subscribeOn(Schedulers.io())
.observeOn(SchedulerProvider.ui())
.map {
InfoStruct(
it.Name.toString(),
it.Id.toString()
)
}
.subscribe(
{println("${it.userName} || ${it.userId}")},
{println("Error")}
)
...
I pass one value to the getById method parameter - an identifier, and send a request like this: select * where id =: id. I want to pass an array of identifiers as a parameter to get data for several users at once, but I don't want to change the structure of the request. How can this be done?
You could use a dao, e.g. getByManyIds(), that uses a WHERE clause that returns a list based upon a provided list.
The SELECT clause could be along the lines of
#Query("SELECT * FROM the_table WHERE id IN (:idlist)"
List<your_type> getByManyIds(appropriate_type idlist);
appropriate_type should be an array of the id's int[], long[], String[] etc as is suitable (Room will generate the appropriate comma separated list).
Assuming that your Dao method looks like this:
#Query("SELECT * FROM user WHERE id = :id"
Single<User> getById(String id);
You need to do is change it to this:
#Query("SELECT * FROM user WHERE id IN (:ids)"
Single<List<User>> getByIds(List<String> ids);
And then use it like that:
userDatabase.userDao().getByIds(listOfIds)
.subscribeOn(Schedulers.io())
.observeOn(SchedulerProvider.ui())
.map { users ->
users.map {
InfoStruct(
it.Name.toString(),
it.Id.toString()
)
}
}
....
i have a query like this
#Query("SELECT * FROM table WHERE type IN(:types) AND selection = 0 ORDER BY timestamp DESC")
my problem is that i have one type in my type list lets say it's type=4 for which i want selection = 1.
Is it possible to get the results in one query and how should the query look like?
So I have a room database all set up, everything is fine, so I can make queries and inserts, delete etc no problems, however i've just run into a situation where id like to return entries by their Ids and duplicates should be allowed, however room is removing the duplicates, so for instance I send it a list of ids say <1,2,3,2,3> and it returns items by their ids but only sends me <1,2,3> removing the duplicate entries. The query I'm making is below (btw complete noob at sql)
#Query("SELECT * FROM card WHERE cardId IN(:cardId)")
LiveData<List<Card>> getCardsByIds(List<Integer> cardId);
Im using it via a repository I created (just a level of abstraction) and calling this repo from a ViewModel, this ViewModel has a mutable live data integer list containing the ids and using a SwitchMap I get the latest live data. ill include the relevant pieces below
CARD REPO calls my Daos method like this
public LiveData<List<Card>> getCardsByIds(List<Integer> cardIds){
return cardDao.getCardsByIds(cardIds);
}
ViewModel calls for them
private MutableLiveData<List<Integer>> cardIds;
//** constructor etc
cards = Transformations.switchMap(cardIds, id -> cardRepository.getCardsByIds(id));
and through the magic of SwitchMap when the cardIds list updates a new query is made and I observe the ViewModel from my fragment. I've debugged it so I know the list of Ids is correct and has the duplicates Ids, but the returned LiveData list is missing the duplicate Ids. any help?
Edit:
The SQLiteDatabase always presents the results as a Cursor in a table format that resembles that of a SQL database.
Source : Google Developer Training
Before the results are returned by the query, the results are stored in a table, and if there are rows with duplicate primary keys, they would be omitted by default.
To achieve what you intend, you can execute a query to find single element by id in loop and append the result to a list.
Updated DAO method:
#Query("SELECT * FROM card WHERE cardId=:cardId")
LiveData<Card> getCardById(Integer cardId);
Update Repository method:
public LiveData<List<Card>> getCardsByIds(List<Integer> cardIds){
List list = new ArrayList();
for(Integer cardId: cardIds){
list.append(cardDao.getCardById(cardId));
}
return list;
}
Hope this helps.
Original Answer:
If id is the primary key of your model, It doesn't allow duplicate data to be entered. Hence while retrieving you might find duplicates missing.
If you have id with duplicate, create another attribute for primary key. (use autogenerate if you don't have any primary key attribute)
A primary key is by default UNIQUE and NOT NULL.