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 |
Related
UniqueID | MobileNumber | createDate
-----------+---------+-----+------------+-----------
U_23121 | 987654 | 2013-02-05
U_23124 | 987654 | 2013-02-02
U_23122 | 845263 | 2013-01-18
U_23128 | 654789 | 2013-01-16
U_23123 | 735689 | 2013-01-12
U_23128 | 654789 | 2013-01-11
U_23128 | 654789 | 2013-01-10
U_23126 | 987654 | 2013-01-09
U_23125 | 845263 | 2013-01-07
U_23126 | 845263 | 2013-01-06
U_23125 | 987654 | 2013-01-05
I want to record like filtering with mobile number if more then one continue get latest based on createdDate and get count for that like
UniqueID | Mobile_Number | createDate | count
-----------+---------+-----+------------+-----------
U_23121 | 987654 | 2013-02-05 | 2
U_23122 | 845263 | 2013-01-18 | 1
U_23128 | 654789 | 2013-01-16 | 1
U_23123 | 735689 | 2013-01-12 | 1
U_23128 | 654789 | 2013-01-11 | 2
U_23126 | 987654 | 2013-01-09 | 1
U_23125 | 845263 | 2013-01-07 | 2
U_23125 | 987654 | 2013-01-05 | 1
I'll get record that is need from following query but not getting count
SELECT te.*
FROM tableName as te
WHERE te.Mobile_Number <> (select Mobile_Number
from tableName
where createDate > te.createDate
limit 1
)
ORDER BY te.createDate DESC
This is a gaps-and-islands problem. One solution is to assign a "grp" to each row and then aggregate by that group.
You can assign the grp by counting the number of mobile numbers that are different from the mobile number in each row, up to that row. This is a constant value for adjacent mobile numbers.
The resulting query:
SELECT MAX(UniqueId), MobileNumber,
MAX(createDate), COUNT(*)
FROM (SELECT te.*,
(SELECT COUNT(*)
FROM tableName te2
WHERE te2.createDate < te.createDate AND
te2.MobileNumber <> te.MobileNumber
) as grp
FROM tableName te
) te
GROUP BY MobileNumber, grp;
ORDER BY MIN(tcreateDate) DESC
Ok, this is the gaps and islands problem. If your Sqllite supports the row_number function (version 3.25 and more) then you can use the following approach
select MobileNumber, max(createDate), count(*)
from
(
select *,
row_number() over (order by createDate) -
row_number() over (partition by MobileNumber order by createDate) grp
from data
) t
group by grp, MobileNumber
USE GROUP BY
SELECT te.* FROM tableName as te where te.Mobile_Number != (select Mobile_Number from tableName where createDate > te.createDate limit 1) GROUP BY Mobile_Number ORDER BY te.createDate DESC
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;
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.
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.
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));