Room SQL query to retrieve entity key and sum of values - android

My database contains a list of these "Movement" class:
#PrimaryKey (autoGenerate = true)
private int NumeroDeOperacion;
private int FechaYear;
private int FechaMonth;
private int FechaDay;
private String TipoOperacion;
private String Category;
private String Notas;
private float Quantity;
In one of my queries I'd like to retrieve only Category and Quantity so I created another POJO object like this:
public class Category {
#ColumnInfo(name = "Category")
public String name;
#ColumnInfo(name = "Quantity")
public float quantity;
public Category(){}
}
What I'm triying to get is all the different Category in a specific year and the SUM of all Quantity.
So, let's say I have something like this:
Category Quantity
A 5
B 10
C 5
A 15
B 20
I'd like to get:
Category Quantity
A 20
B 30
C 5
I tried with this query but it is only getting the last entry of each Category:
#Query("SELECT DISTINCT Category, Quantity FROM OperacionesTable WHERE FechaYear = :year GROUP BY CategoryORDER BY Quantity DESC")
LiveData<List<Category>> getGastosCategoryTotalsInYear(int year);
Any help would be much appreciated.
Thanks in advance

To sum the quantities, you have to use SUM.
Also, there is no need for DISTINCT, since GROUP BY already takes care of that. My guess is that you added distinct, because there was an error. The error was there, because Quantity was neither in the group by columns, nor used in an aggregate function. This is typically an error (except in MySQL, which will just give you a random result).
Anyway, this should do the trick:
SELECT
Category,
SUM(Quantity) as TotalQuantity -- Column alias, to give the column a proper name
FROM
OperacionesTable
WHERE
FechaYear = :year
GROUP BY
Category
ORDER BY SUM(Quantity) DESC

Related

order by date is not working in android 11 sqllite

I am getting a weird problem.
with SQL lite query in android 11 devices only.
#Query("SELECT *, SUM(case when isReadMessage = 0 then 1 else 0 end) as countMessage from chat_message_history\n" +
" where messageUser is not null GROUP BY messageUser ORDER by messageDate desc")
LiveData<List<MessagesData>> getAllLiveUniqueUsers();
The DAO class
#Entity(tableName = "chat_message_history", indices = {
#Index(value = "mesId")})
public class MessagesData {
#PrimaryKey(autoGenerate = true)
private int mesId;
private String message;
#TypeConverters(DateConverter.class)
private Date messageDate;
private boolean isReadMessage;
private int countMessage;
private String messageUser;
...}
Date Converter class
public class DateConverter {
#TypeConverter
public static Date toDate(Long timestamp) {
return timestamp == null ? null : new Date(timestamp);
}
#TypeConverter
public static Long toTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
The output should be order by date which is working in android 6 - android 10. In android 11 its not working.
Please help me to solve this problem.
Maybe your query worked coincidentally in previous versions, but actually it is wrong.
It is an aggregation query that counts the number of unread messages of each user of the table chat_message_history.
The flaw in your query is that you want to sort by the date of the message, but which date?
For each user exist many messages.
Which of these dates do you want to be used in the final sorting?
Maybe you want the first or maybe the last.
In this case, SQLite will chose arbitrarily a date (usually it picks the first but this is not guaranteed).
Use an aggregation function like MIN() or MAX() in the ORDER BY clause and also simplify the CASE expression:
SELECT *, SUM(isReadMessage = 0) AS countMessage
FROM chat_message_history
WHERE messageUser IS NOT NULL
GROUP BY messageUser
ORDER by MAX(messageDate) DESC;
Everything I mentioned above about SQLite picking arbitrary values for messageDate also apply the values of the columns returned by SELECT *.
It would be better if you return only aggregated columns like:
SELECT messageUser,
MAX(messageDate) last_date,
SUM(isReadMessage = 0) AS countMessage
FROM chat_message_history
WHERE messageUser IS NOT NULL
GROUP BY messageUser
ORDER by last_date DESC;

Android Room: select list of custom objects removing duplicates by a specific property

I'm using Room library to retrive a List without duplicates for property "text".
This is the code of the query in MyObjectDao class:
#Query("SELECT DISTINCT * FROM historyentity WHERE text LIKE :inputText || '%'")
List<MyObject> findByText(String inputText);
I also post MyObject class:
#Entity
public class MyObject {
#PrimaryKey(autoGenerate = true)
public int uid;
#ColumnInfo(name = "text")
public String text;
#ColumnInfo(name = "timestamp")
public Long timestamp;
}
Anyway I still get get results with duplicates for field "text". How can I get a List that does not contains duplicates on field "text"?
For example if I have the following three elements in the database
database.addMyObject(new MyObject("dog", System.currentTimeInMills());
database.addMyObject(new MyObject("cat", System.currentTimeInMills());
database.addMyObject(new MyObject("dog", System.currentTimeInMills());
when I call my query I want to get only the first two elements.
If you want just list with unique text values you can try this one:
#Query("SELECT DISTINCT text FROM historyentity WHERE text LIKE :inputText || '%'")
List<String> findByText(String inputText); // <-- changed type to List<String>
UPDATE
You can try this query (it gets only one item with text value - with maximal id - or you can use maximal (or minimal) timestamp):
Select * from historyentity as t1
INNER JOIN (select text,max(uid) as uid from historyentity WHERE text LIKE :inputText group by text) t2
ON t1.text = t2.text and t1.uid = t2.uid

In Room db Dao class- how to get values from table by comparing distinct values of a column?

I'm working on Room database, and I want to get two columns values(Category and total amount) from IncomeExpense table by comparing distinct values in category column. Let me explain, for example in category column there are 4 rows which have same value(cash), what I want is to calculate total amount of amount column where category is cash and category value (which is cash in this case).
I take these categories values from another table (Category table) in which user can add edit or delete categories.
The problem is that I don't know how to compare category with those values user added in category column which dynamic in this case.
This is my Entity class.
#Entity
public class IncomeExpense {
#PrimaryKey(autoGenerate = true)
private int id =0;
private String type;
private int amount;
private String category;
private String date;
private String time;
private String mode;
private String note;
This is Dao class where I have to write this query
#Query("SELECT SUM(amount), category from IncomeExpense WHERE category like 'What should I write here to get these values in this case'");
I just want to get the total amount and category value in this case
you can use group by clause, this will return a list on IncomeExpense but amount will be grouped as per category
#Query("SELECT SUM(amount) as amount,category from IncomeExpense GROUP BY category");
public List<IncomeExpense> getCategoryPrice();
For Example:
Database Has:
[ (10, Cash), (50, Cash), (20, Credit), (10, Credit) ]
The above query will return
[ (60, Cash), (30, Credit) ]

Room - find sum of objects by string?

I have problem with queries in Room. I have entity where is String field called Type. I want to make a query that will allow me to get the sum of objects by type. So if I have 4 expenses with Bills type I want to get them as a sum.
Expense:
#Entity(tableName = "expense_table")
public class Expense {
#PrimaryKey(autoGenerate = true)
private int expenseId;
private String note;
private Double value;
private String type;
Table of defined types:
private String[] expenses = {"Bills", "Car", "Child", "Clothes", "Entertainment", "Education", "Electronics",
"Food", "Health", "Home", "Pet", "Shopping", "Transport", "Travel", "Others"};
Query in Dao:
#Query("SELECT SUM(value) FROM expense_table GROUP BY type")
LiveData<List<Double>> getTotalType();
In query above I'm getting the sum of every single type, but I do not know which one is which. I need this information because I want to set sum of types in chart. So my question is: Is it possible to make one query to get every single sum with name of type, or rather I need to make every query for every single type?
You need to add the type to your query and create a POJO to hold both values(the type and its corresponding total):
#Query("SELECT type, SUM(value) as total FROM expense_table GROUP BY type")
LiveData<List<TypeWithSum>> getTotalType();
where TypeWithSum is:
public class TypeWithSum {
private String type;
private double total;
public TypeWithSum(String type, double total) {
this.type = type;
this.total = total;
}
}

How to get specific column using Android Room

I'm trying to get id column from my database, ad it to ArrayList and to each id add "\t0",
My database is created using Room, i have a lot of column which one of them is
#PrimaryKey(autoGenerate = true)
private int id;
I am operating using ItemDAO and i have there function
#Query("SELECT * FROM item")
List<Item> getItems();
Which writes to ArrayList<Items> all of contents
I was thinking of running it trough the loop getting id and adding to ArrayList<String> but this doesn't seems to be eficient.
Your DAO:
#Query("SELECT Id FROM item")
List<Integer> getAllIds();
Your model:
#ColumnInfo(name = "Id")
#PrimaryKey(autoGenerate = true)
private int id;
In you query SELECT * FROM item * means select All, put there your column name and you will get list of objects from that column
Example: Select all items in id column SELECT id FROM item
I tried to modify and test #Valgaal 's solution. It turns out that Room can also return other type of values, more than just id (or integer).
For example, you can write an item class like this:
#Entity(tableName = Item.TABLE_NAME)
public class Item {
public static final String TABLE_NAME = "ItemsTable";
public static final String COL_DESC = "Description";
#PrimaryKey(autoGenerate = true)
private int id;
#ColumnInfo(name = COL_DESC)
private String description;
// getter & setter...
}
And then, you can write Dao like this:
#Dao
public interface ItemDao {
#Query("SELECT * FROM " + Item.TABLE_NAME)
List<Item> getItems();
#Query("SELECT " + Item.COL_DESC + " FROM " + Item.TABLE_NAME)
List<String> getItemDescriptions();
}
And it's functional as it should be.
I guess all of the other data types that Room can save (including custom types?) can be queried (and returned lists of specific column data) by the same logic above. Hope this would help someone in the future!
For returning multiple columns, create a pojo class that can be set as a return type for your DAO function
Note the select query should contain the Pojo class variable name (can be done via AS keyword)
Detailed answer here
https://stackoverflow.com/a/50802209/1029110
I landed on this question for my issue...but didnt find answer. So this may help others.

Categories

Resources