I have an (Android) SQLite table with two columns, Col1 and Col2, containing text. I want to update Col1 to contain the text with the maximum length out of Col1 and Col2 from the same row. I already have a working query but that query takes pretty long to execute on a large data set.
Example data:
| Col1 | Col2 | ...
---------------
| AB | A |
| A | ABC |
| AB | ABCD |
Expected update result:
| Col1 | ...
--------
| AB |
| ABC |
| ABCD |
Working (but slow and hard to read) query:
UPDATE table
SET Col1 = (
SELECT Col2
FROM table AS innerTable
WHERE table.ROWID = innerTable.ROWID)
WHERE length(Col1) < length(Col2)
I am basically looking for something like this, without nested queries:
UPDATE table SET Col1 = maxLengthString(Col1, Col2)
Is there any existing function I have overlooked? Note that this is SQLite, so I can not use CREATE FUNCTION.
Thank you for your help!
I think that it is as simple as that:
update tablename
set col1 = col2
where length(col2) > length(col1);
Only the rows where the length of col1 is less than the length of col2 will be updated.
See the demo.
Results:
| Col1 | Col2 |
| ---- | ---- |
| AB | A |
| ABC | ABC |
| ABCD | ABCD |
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;
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.
I have a one table question_table and one ImageButton (Back). I need to get the last inserted record from the database after clicking on the Back.
My row contains the following columns: question, optionA, optionB, optionC, optionD, and I need the data for use on my Activity. I create one method in database but it's not working.
Here is code for reference:
MySQLiteHelper.java extract:
public List<ObjectiveWiseQuestion> getLastInsertQuestion()
{
// long index = 0;
List<ObjectiveWiseQuestion>LocwiseProfileList=new ArrayList<ObjectiveWiseQuestion>();
db = getReadableDatabase();
Cursor cursor = db.query(
"sqlite_sequence",
new String[]{"seq"},
"name = ?",
new String[]{TABLE_QUESTION},
null,
null,
null,
null );
if (cursor.moveToFirst())
{
do {
ObjectiveWiseQuestion owq= new ObjectiveWiseQuestion();
owq.setQuestion(cursor.getString(2));
owq.setOptionA(cursor.getString(3));
owq.setOptionB(cursor.getString(4));
owq.setOptionC(cursor.getString(5));
owq.setOptionD(cursor.getString(6));
owq.setCorrectOption(cursor.getString(7));
LocwiseProfileList.add(owq);
} while(cursor.moveToNext());
db.close();
}
return LocwiseProfileList;
}
OnClickListner from AddQuestionActivity.java
imgBack.setOnClickListener( new View.OnClickListener()
{
#Override
public void onClick(View v)
{
msg();
emptyFormField();
try {
final List<ObjectiveWiseQuestion> LocWiseProfile = db.getLastInsertQuestion();
for (final ObjectiveWiseQuestion cn : LocWiseProfile)
{
db=new MySQLiteHelper(getBaseContext());
db.getWritableDatabase();
txtQuestion.setText(cn.getQuestion());
txtOptionA.setText(cn.getOptionA());
txtOptionB.setText(cn.getOptionB());
txtOptionC.setText(cn.getOptionC());
txtOptionD.setText(cn.getOptionD());
txtCorrectOption.setText(cn.getCorrectOption());
db.close();
}
} catch(Exception e) {
e.printStackTrace();
}
}
});
Please give me some hint.
I think the top answer is a bit verbose, just use this
SELECT * FROM table ORDER BY column DESC LIMIT 1;
Try this:
SELECT *
FROM TABLE
WHERE ID = (SELECT MAX(ID) FROM TABLE);
OR
you can also used following solution:
SELECT * FROM tablename ORDER BY column DESC LIMIT 1;
To get last record from your table..
String selectQuery = "SELECT * FROM " + "sqlite_sequence";
Cursor cursor = db.rawQuery(selectQuery, null);
cursor.moveToLast();
Here's a simple example that simply returns the last line without need to sort anything from any column:
"SELECT * FROM TableName ORDER BY rowid DESC LIMIT 1;"
I think it would be better if you use the method query from SQLiteDatabase class instead of the whole SQL string, which would be:
Cursor cursor = sqLiteDatabase.query(TABLE, allColluns, null, null, null, null, ID +" DESC", "1");
The last two parameters are ORDER BY and LIMIT.
You can see more at:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
If you have already got the cursor, then this is how you may get the last record from cursor:
cursor.moveToPosition(cursor.getCount() - 1);
//then use cursor to read values
Another option is to use SQLites LAST_VALUE() function in the following way.
Given this table:
+--------+---------+-------+
| OBJECT | STATUS | TIME |
+--------+---------+-------+
| | | |
| 1 | ON | 100 |
| | | |
| 1 | OFF | 102 |
| | | |
| 1 | ON | 103 |
| | | |
| 2 | ON | 101 |
| | | |
| 2 | OFF | 102 |
| | | |
| 2 | ON | 103 |
| | | |
| 3 | OFF | 102 |
| | | |
| 3 | ON | 103 |
+--------+---------+-------+
You can get the last status of every object with the following query
SELECT
DISTINCT OBJECT, -- Only unique rows
LAST_VALUE(STATUS) OVER ( -- The last value of the status column
PARTITION BY OBJECT -- Taking into account rows with the same value in the object column
ORDER by time asc -- "Last" when sorting the rows of every object by the time column in ascending order
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING -- Take all rows in the patition
) as lastStatus
FROM
TABLE
The result would look like:
+--------+--------------+
| OBJECT | LAST_STATUS |
+--------+--------------+
| | |
| 1 | ON |
| | |
| 2 | ON |
| | |
| 3 | ON |
+--------+--------------+
Suppose you are looking for last row of table dbstr.TABNAME, into an INTEGER column named "_ID" (for example BaseColumns._ID), but could be anyother column you want.
public int getLastId() {
int _id = 0;
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.query(dbstr.TABNAME, new String[] {BaseColumns._ID}, null, null, null, null, null);
if (cursor.moveToLast()) {
_id = cursor.getInt(0);
}
cursor.close();
db.close();
return _id;
}
Just simple, you can move with Cursor moveToLast(); method provides to move to the last record
cursor.moveToLast();
I wanted to maintain my table while pulling in one row that gives me the last value in a particular column in the table. I essentially was looking to replace the LAST() function in excel and this worked.
, (Select column_name FROM report WHERE rowid = (select last_insert_rowid() from report))
in sqlite, there is a table called sqlite_sequence, this table contains the table name and it's last id number (if the id is auto incremented).
So, to get the last row in a table just put :
Select * from TABLENAME where id=(SELECT * from sqlite_sequence where name ='TABLENAME')
The previous answers assume that there is an incrementing integer ID column, so MAX(ID) gives the last row. But sometimes the keys are of text type, not ordered in a predictable way. So in order to take the last 1 or N rows (#Nrows#) we can follow a different approach:
Select * From [#TableName#] LIMIT #Nrows# offset cast((SELECT count(*) FROM [#TableName#]) AS INT)- #Nrows#
Also, if your table has no ID column, or sorting by id doesn't return you the last row, you can always use sqlite schema native 'rowid' field.
SELECT column
FROM table
WHERE rowid = (SELECT MAX(rowid) FROM table);
Sometimes there is no ID column and ROWID does not help.
You may use simple query, which is universal (IMHO):
Select * from TABLE_NAME limit 1 offset ((select count() from TABLE_NAME) - 1)
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));