I am implementing a messenger function for my android app and save every received and sent message in the following sqlite schema:
CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`message_id` TEXT,
`sentTimestamp` INTEGER NOT NULL,
`senderUserID` TEXT,
`senderUsername` TEXT,
`senderProfilePictureUrl` TEXT,
`receiverUserID` TEXT,
`receiverUsername` TEXT,
`message` TEXT)
Now I want to have an overview about all my chats (like in WhatsApp) with the repective last message received or sent. I need all fields (SELECT *). The problem is that every chat partner must only appear once and if I was the last sender my last message should appear on the list.
Example:
User other sends "How are you?" to user me.
User me sends "I am good" to user other.
Expected result:
+----------+-------------+
| User | Message |
+----------+-------------+
| other | I am good |
+----------+-------------+
This is what I have so far
SELECT * FROM "+MESSAGE_TABLE+"
GROUP BY senderUserID, receiverUserID
ORDER BY id DESC
but the result looks like this:
+--------------+----------------+
| User | Message |
+--------------+----------------+
| other | How are you? |
| me | I am good |
+--------------+----------------+
How can I achieve this? Is this even possible with just 1 table so that I cannot make joins?
do like :
SELECT * FROM "+MESSAGE_TABLE+" where senderUserID NOT IN (SELECT distinct receiverUserID from "+MESSAGE_TABLE+")
GROUP BY senderUserID, receiverUserID
ORDER BY id DESC
Related
For the sake of this scenario I have a user table and two tables where each user can be of one or two types, friend and family tables respectively. These two only contain the ids if the users stored in the user table.
I am trying to do the following:
Return all users that are friends or family, ordered by name and grouped by type.
So far I've had almost no trouble, the problem comes up when I want to group by type inside the query and add separators in the RecyclerView to distinguish a user that is a friend and a user that is family.
My intention is to add some sort of boolean value in the query itself to serve as a flag and thus distinguish the users that are being returned in the same list, but I am having immense difficulty in finding any sort of guidance or examples on how to do this.
This is an example (non-working) of what I am trying to do:
#Query("" +
"SELECT " +
"*, " +
"table source? as type " + // here
"FROM UserFamily " +
"LEFT JOIN User " +
"ON UserFamily.id = User.id " +
"LEFT JOIN UserFriend " +
"ON User.status = UserFriend.id " +
"ORDER BY name ASC " +
"GROUP BY ... table source? " // here
)
How can this be achieved? I understand I could just add all the different types as columns in the user table and boolean each one, but this is not an option.
EDIT: Sample data as requested
User table
| id | first_name | age |
|:--:|:----------:|:---:|
| 1 | Danny | 28 |
| 2 | Susan | 15 |
| 3 | Lenny | 45 |
Friend table (id is a foreign key belonging to User table)
| id |
|:--:|
| 3 |
Family table (id is a foreign key belonging to User table)
| id |
|:--:|
| 1 |
Desired results:
| id | first_name | age | type |
|:--:|:----------:|:---:|:----:|
| 1 | Danny | 28 | 1 |
| 3 | Lenny | 45 | 2 |
Where type would represent a user that is family or friend by 1 and 2, sorted by first_name and grouped by type.
I guess what you want is use field type like this:
CASE
WHEN UserFamily.id IS NOT NULL THEN 1 // type = 1 means it's a family
WHEN UserFriend.id IS NOT NULL THEN 2 // type = 2 means it's a friend
else 0 // type = 0 means it's neither family not friend
END as type
In my application, I have a database table containing chat messages,like below.
|---------------------------------------------|
|message | from | to |time
|-------------|-------|------|----------------|
|Hello |user1 |user2 |2015-2-26 1:15PM|
|-------------|-------|------|----------------|
|Watsup |user2 |user1 |2015-2-26 1:25PM|
|-------------|-------|------|----------------|
|Hows u? |user3 |user1 |2015-2-26 2:15PM|
|-------------|-------|------|----------------|
|Im fine |user1 |user3 |2015-2-26 2:35PM|
----------------------------------------------|
In my messages page I want list messages from all users. In this condition assume, "user1" as log-inned user,
Currently I am using query,
SELECT * FROM table GROUP BY from
and I am getting output as,
|--------------------------------|
|user2 |
|Hello |
|--------------------------------|
|user2 |
|Watsup |
|--------------------------------|
|user3 |
|Hows u? |
|--------------------------------|
|user3 |
|Im fine |
|--------------------------------|
What I want is distinct rows (like all chat apps),
|--------------------------------|
|user2 |
|Watsup |
|--------------------------------|
|user3 |
|Im fine |
|--------------------------------|
So, how can I write a sqlite query to fetch rows like this?
You can try as below with the Group By and Having clause.
SELECT message,from
FROM
table
GROUP BY from
HAVING Max(time) = Time
You can try something like this:
SELECT * FROM table GROUP BY MIN(from, to), MAX(from, to) ORDER BY time DESC
This will not treat GROUP BY of (userA, userB) and (userB, userA) as different and combine the two, so you will get the output as you want.
You can also JOIN this with your Contacts table so that you can get all the data you need to show on the "Recent Chats" screen in one go. Try something like this:
SELECT * FROM messages m, Contacts c WHERE (m.from = c.userid OR m.to = c.userid) GROUP BY MIN(m.from, m.to), MAX(m.from, m.to) ORDER BY m.time DESC
Use DISTINCT AND ORDERBY :
SELECT DISTINCT from,message FROM table ORDER BY time DESC;
I have following data:
me = my_userid;
Table: Message
message_id | message_from | message_to
1 | me | user
2 | user | me
Running query gives two rows (SELECT DISTINCT message_from,message_to FROM Message WHERE message_from ='"+me+"' OR message_to ='"+me+"'");
Used OR because my id can be in from(when sending) or in TO (when other user sends me message)
-- This returns two rows however i want it to return one row because if you switch to - from you get same ids, So how can this be done in the query. Thanks
You can use min() and max() as scalar functions:
select distinct min(message_from, message_to) as m1, max(message_from, message_to) as m2
from message
where message_from ='"+me+"' OR message_to ='"+me+"'"
These are equivalent to least() and greatest() in other databases.
My problem
I am actually developing an SQLite database for an android application. I come from MySQL, where the query I'll expose works nicely.
This is my database structure:
table1: mid int(1) primary key autoincrement, name varchar(256)
table2: aid int(1) primary key autoincrement, name varchar(256)
With data inserted:
table1, row1: 1, "abc"
table2, row1: 1, "def"
What I want to do
I want to do a union so that the resulting data is:
| mid | aid | name |
--------------------
| 1 | 0 |"abc" |
| 0 | 1 |"def" |
So, I came up with this simple query:
select mid, name, 0 as aid from table1 union select aid, name, 0 as mid from table2;
However, I'm getting this back:
| mid | name | aid |
--------------------
| 1 |"abc" | 0 |
| 1 |"def" | 0 |
(I don't mind the column order)
This is of course not what I am looking for, and I can't see what I am doing wrong.
Any help will be appreciatted.
Thank you.
Maybe it's the column order that's tripping it up?
How about
select mid, 0 as aid, name from table1 union select 0 as mid, aid, name from table2;
works for me, at least on SQLFiddle: http://sqlfiddle.com/#!2/157f09/1
I have a table orders, consisting of 3 columns:
order_id int primary key,
cust_id integer,
order_date integer
with data:
order_id | cust_id | order_date
1 | 10 | 1325376000
2 | 10 | 1325548800
3 | 10 | 1325894400
4 | 11 | 1325462400
5 | 11 | 1325721600
6 | 12 | 1325721600
7 | 12 | 1326326400
I'm trying to write a query to give a Cursor containing the most recent order for a given customer that I can then pass to a SimpleCursorAdapter and bind to a ListView, such that the user sees the following:
10 1325894400 (formatted as human readable date)
11 1325721600
12 1326326400
I've tried joining the table to itself in various ways without any luck:
http://sqlfiddle.com/#!2/77b22d/1/0
If I have to populate an ArrayList and use an ArrayAdapter I will, but I'd like to exhaust this option first. Thanks!
EDIT: Apologize for the differences between here and the SQLFiddle, brain running on two separate threads. The Fiddle is the 'correct' data set.
2nd EDIT: Added a new wrinkle (ignore table above, see the SQL fiddle). Adding a field for free-form text and then running the query returns the first record in the GROUP BY, plus the field for the max_date. I need to pull the whole record containing the date that equals max_date. Adding a WHERE clause breaks the query. Thoughts?
Try this
select
order_number
, cust_number
, order_date
from orders o1
where order_number =
(
select order_number
from orders o2
where o2.cust_number = o1.cust_number
and order_date =
(
select max(order_date)
from orders o3
where o3.cust_number = o2.cust_number
)
)
This will get you the correct records and you can format the date as you like in the main query.
Note: My answer is a bit different form your display since the example here and the Fiddle are different. used the Fiddle one
create table orders (order_number integer primary key,
cust_number integer not null,
order_date integer not null);
insert into orders values (1001,10,1005),
(1,10,1325376000),
(2,10,1325548800),
(3,11,1325894400),
(4,11,1325462400),
(5,11,1325721600),
(6,12,1325721600),
(7,12,1326326400),
(8,12,1326326460);
If you just want the latest record for each customer, I think this will work:
SELECT order_number, cust_number, max(order_date) as max_date FROM orders GROUP BY cust_number
The values you put on the link are different from the ones you posted here but you are looking for:
select o1.cust_number, max(o1.order_date)
from orders o1
group by o1.cust_number
order by o1.cust_number ASC
This will give you for each customer the most recent order.