Android - SQLite Select the first N occurrences of each differing column value - android

Suppose I have a SQL table "songs" with three columns: "title", "artist" and "ranking":
track | artist | ranking
---------+--------+---------
A | A1 | 3
B | A1 | 2
C | A1 | 1
D | A2 | 4
E | A3 | 7
F | A3 | 6
G | A3 | 5
I want to make a SELECT query that will return just the first N (e.g. two) row for each artist while ordering by the ranking. I'm aware that using GroupBy on the artist column will return one row of each artist, however I want two in this scenario like so:
track | artist | ranking
---------+--------+---------
A | A1 | 1
B | A1 | 2
D | A2 | 4
E | A3 | 5
F | A3 | 6
If it is possible, I would preferably want to construct this within android using a queryBuilder, this is as close as I managed to get:
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder qBuilder = new SQLiteQueryBuilder();
String[] sqlSelect = {"title", "artist", "ranking"};
String sqlTable = "songs";
String orderBy = "ranking DESC";
qBuilder.setTables(sqlTable);
cur = qBuilder.query(db, sqlSelect, null, null, null, null, orderBy);
I have seen related questions, however I haven't been able to find a way to apply it to this scenario - any direction on how to accomplish this would be appreciated.

Related

SQLITE select values sum same ID

I have a table called transactions with the following schema:
ID | P_Name | O_ID | P_ID | P_Qty |
===============================================
1 | PRODUCT A | 1 | 140 | 100 |
2 | PRODUCT A | 1 | 140 | 15 |
3 | PRODUCT B | 1 | 130 | 10 |
4 | PRODUCT C | 1 | 120 | 2 |
I want to sum all P_Qty that share a P_Name so I can eventually end up with:
P_Name | P_ID | P_Qty |
===============================
PRODUCT A | 140 | 115 |
PRODUCT B | 130 | 10 |
PRODUCT C | 120 | 2 |
As you can see the P_Qty is summed where the P_ID is same, I am using a ContentResolver as shown below its however failing as shown:
String selection = null;
String[] selectionArgs = null;
String orderBy = TRANSACTION_PRODUCT_NAME + " ASC";
Cursor cursor = getActivity().getContentResolver().query(
SalesManContract.TRANSACTION_CONTENT_URI,
new String[] {TRANSACTION_PRODUCT_NAME," SUM(P_Qty) AS
P_Qty"},
selection,
selectionArgs,
orderBy);
The result is:
P_Name | P_ID | P_Qty |
===============================
PRODUCT A | 140 | 127 |
How can I achieve my desired result using ContentResolver

SQLite many to many join and group

This is a very normal setup for many-to-many relational tables.
product list and category list.
Each product belongs to (0,n) category.
Each category contains (0,n) product.
TABLES
CREATE TABLE product (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL);
CREATE TABLE category (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL);
CREATE TABLE product_category (
product_id INTEGER NOT NULL,
category_id INTEGER NOT NULL);
PRODUCT table
| id | name |
=============
| 1 | p1 |
| 2 | p2 |
| 3 | p3 |
CATEGORY table
| id | name |
=============
| 1 | c1 |
| 2 | c2 |
| 3 | c3 |
PRODUCT_CATEGORY table
| product_id | category_id |
============================
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 3 | 1 |
Question
I would like to know how to query for product by category_id and have the product listed with all category_id that it is in.
For example, I want to query the list of products that are available in category = 1, and the result must contain a categories_id where all categories that the product belongs to must be listed.
Expected output
| product_id | product_name | categories_id |
=============================================
| 1 | p1 | 1,2,3 |
| 2 | p2 | 1,2 |
| 3 | p3 | 1 |
Attempts
I know this can be done with sub query, but I would like to know whether this can be achieved by JOIN statement?
I have tried the following query but the results does not reflect what I want.
JOIN QUERY statement
SELECT
P.id AS product_id,
P.name AS product_name,
GROUP_CONCAT(PC.category_id, ',') AS categories_id
FROM product AS P
LEFT JOIN product_category AS PC
ON P.id = PC.product_id
WHERE PC.category_id = 1
GROUP BY P.id;
Output (not as intended)
| product_id | product_name | categories_id |
=============================================
| 1 | p1 | 1 |
| 2 | p2 | 1 |
| 3 | p3 | 1 |
Can anyone advice on how this can be achieved?
Here is SqlFiddle for the execution and query is
SELECT P.id AS product_id, P.name AS product_name,
GROUP_CONCAT(PC2.category_id) AS categories_id
FROM
product AS P LEFT JOIN product_category AS PC ON
P.id = PC.product_id LEFT JOIN product_category AS PC2 ON
P.id = PC2.product_id
WHERE PC.category_id = 1
GROUP BY P.id;
SELECT
p.id,
p.name,
GROUP_CONCAT(pc2.category_id, ',')
FROM product_category pc1
JOIN product_category pc2
JOIN product p
WHERE pc1.category_id = 1
AND pc1.product_id = pc2.product_id
AND p.id = pc1.product_id
GROUP BY pc1.product_id;

How to combine 2 columns into a new one in sqlite

I have a table with 3 columns and I have to put the values from 2 columns into one in descending order.
+---+---+---+
| A | B | C |
+---+---+---+
| z | 1 | 2 |
| f | 5 | 7 |
| s | 9 | 5 |
+---+---+---+
Using this example the output would be putting the values from column B and C into one like this:
+---+----+
| A | B |
+---+----+
| s | 9 |
| f | 7 |
| f | 5 |
| s | 5 |
| z | 2 |
| z | 1 |
+---+----+
My current code:
String SELECT_QUERY = "SELECT a, b, c AS b FROM _table ORDER BY b DESC" ;
How can I do this?
Thanks.
First combine the two queries using UNION and then do the descending order to the combined result.
Query
SELECT * FROM
(
SELECT A,B
FROM tbl
UNION
SELECT A,C
FROM tbl
)t
ORDER BY t.B DESC;
In your case,
String SELECT_QUERY = "SELECT * FROM (SELECT A,B FROM _table UNION SELECT A,C FROM _table)t ORDER BY t.B DESC" ;
Fiddle demo for your reference
Screenshot
Hope this will help you out.

Update row in SQLite without all information from the dataset

I create some Objects based on information from my database. My table looks like this:
tbl_Book
+-----+-------+---------+-------+------+
| _id | Title | Author | Pages | ISBN |
+-----+-------+---------+-------+------+
| 1 | Test1 | Author1 | 111 | 1234 |
| 2 | Test2 | Author2 | 222 | 2345 |
| 3 | Test3 | Author | 333 | 3456 |
+-----+-------+---------+-------+------+
My created Objects only need the information from id, title and the ISBN so I only select these values from the database to create my Object. Now I want to update only the ISBN in the database so I have a method in my Object with this code:
Book b = new Book(id, title, isbn);
b.setISBN(value);
// Code from setISBN
public void setISBN(int isbn)
{
this.isbn= isbn;
// DB updaten
ContentValues cv = new ContentValues();
cv.put("_id", getId());
cv.put("ISBN", isbn);
db.replace("tbl_Book", null, cv);
}
But with this method it comes to a SQLiteConstraintException because author, title and page are null. How can I update a row in an table if I only have some information from the dataset? All other items from the dataset should not be touched.
Why not using Update()? It seems that the _id is your table's primary key. If your intention is just to update a record when you already have the primary key then it should be pretty simple:
String whereClause = "_id=" + getId();
ContentValues cv = new ContentValues();
cv.put("ISBN", isbn);
//update(String table,ContentValue value, String whereClause, String[] whereArgs)
db.update("tbl_Book", cv, whereClause, null);
As far as I know (maybe I'm wrong), Replace() will first delete a row if it exists and then inserts a new record based on provided values. In your case I think, it deletes the corresponding record (based on the id) and then try to insert new one:
For instance let's say the _id is 1:
+-----+-------+---------+-------+------+
| _id | Title | Author | Pages | ISBN |
+-----+-------+---------+-------+------+
| 1 | Test1 | Author1 | 111 | 1234 |
will be replaced by:
+-----+-------+---------+-------+------+
| _id | Title | Author | Pages | ISBN |
+-----+-------+---------+-------+------+
| 1 | NULL | NULL | NULL | 4321 |
Which I don't think that fits your need. Therefore, I think for your purpose the Update suits better.

How can i fetch the last value inserted into sqlite Database

I have a doubt to be clarified. How can i fetch the last value inserted into sqlite DB. I need code for that.I tried using query like this:
SELECT uname,umessage,utime FROM chatmessage ORDER BY utime DESC limit 1;
Where am i doing wrong?? I need help in this issue.
Thanks in advance.
SQLiteDatabase returns id of inserted row. You can rememember this id in some value and use it.
long lastId = db.insert(......);
if the value is last its id should be maximum
you can fire the query like this
c = db.rawQuery("SELECT uname,umessage,utime FROM tablename WHERE " +
"Id = (SELECT MAX(Id) FROM tablename ); ",null);
for last message by particular user add user id column in the message table like
id | userid | message | utime
1 | 1 | wlhf | 3:10
2 | 3 | dfhhfjh | 2:15
3 | 1 | kjfedhr | 4:00
4 | 2 | hejhe | 1:15
5 | 3 | kegekr | 3:30
6 | 1 | wlhf | 3:10
7 | 3 | dfhhfjh | 2:15
8 | 1 | kjfedhr | 4:00
9 | 2 | hejhe | 1:15
10 | 3 | kegekr | 3:30
c = db.rawQuery("
select message from table1 where
userid = 1 ; ",null);
recieve like
ArrayList<String> listMessg = new ArrayList<String>();
cursor = dbm.columnValueofCourse();
cursor.moveToFirst();
startManagingCursor(cursor);
for (int i = 0; i < cursor.getCount(); i++) {
reciv = cursor.getString(cursor
.getColumnIndex("message"));
listMessg.add(reciv_Par);
}
int sizeoflist = listMessg.size();
because in ascending order , the last index
of array list will be the last message of the user
System.out.println("THE LAST MESSAGE BY USER IS " + listMessg.et(sizeoflist -1));

Categories

Resources