I have a chat app and I'm using PHP to get the data from MYSQL. I don't know how to word this the best way so I'm going to illustrate it the best way I can. Below is the an example the database setup.
DATABASE
ID MESSAGE DATETIME
------------------------------------------
1 Hello1. 2019-04-23 23:04:31
1 Hello2. 2019-03-23 10:04:31
1 Hello3. 2019-04-26 22:04:31
1 Hello4. 2019-04-23 13:01:10
2 Hello5. 2019-04-09 23:04:31
2 Hello6. 2019-04-23 23:04:31
2 Hello7. 2019-04-12 23:04:12
2 Hello8. 2019-04-11 20:04:31
3 Hello9. 2019-05-18 19:04:29
3 Hello10. 2019-02-22 23:04:31
3 Hello11. 2019-03-25 23:04:30
4 Hello12. 2019-04-23 15:04:31
4 Hello13. 2019-04-10 23:04:31
5 Hello14. 2019-01-14 23:04:31
SHOULD SELECT
ID MESSAGE DATETIME
------------------------------------------
1 Hello3. 2019-04-26 22:04:31
2 Hello6. 2019-04-23 23:04:31
3 Hello9. 2019-05-18 19:04:29
4 Hello12. 2019-04-23 15:04:31
5 Hello14. 2019-01-14 23:04:31
What I am trying to do is select the newest ID once for each different ID. So for ID 1 I would only be selecting the one with the newest DATETIME and so on and so forth.
mysql_query("SELECT * FROM messages WHERE ____?____ ORDER BY __?__");
So in this case there should only be 5 results. One of each id with the newest dateline. Any help would be greatly appreciated. Thanks.
You want the MAX(date) value, but one per ID. Because you also want the message, which does not appear in the GROUP BY clause, you should run a join on the table towards itself.
In the joined table, you get the maximum date and the ID, grouped by the ID - this gives you the highest date for each ID. Join that on your table on the ID and date, which allows you to get other columns that do not exist in the GROUP BY (as this GROUP BY is in the joined table, you don't need it in the main table).
SELECT m.id, m.message, m.date
FROM messages m
JOIN (
SELECT id, MAX(date) AS date
FROM foo
GROUP BY id
) AS t
ON m.id=t.id AND m.date=t.date
SQL fiddle shows the live result http://sqlfiddle.com/#!9/c70c3/7
You could try sorting them in a subquery before grouping by the ID as follows:
SELECT * FROM (SELECT * FROM messages ORDER BY DATETIME DESC) AS sortedMessages GROUP BY ID;
OR
mysql_query("SELECT * FROM (SELECT * FROM messages ORDER BY DATETIME DESC) AS sortedMessages GROUP BY ID;");
Or you could build a second table with conversations , that could have a subject and the latest message in the row , and then you would just return that full table, when opening the conversation you would pull the indivual messages from the messages table based on the conversationID
Related
I have a table which is having some report info. In that table I have userid and areaname .
Now my requirement is to get the count of user's list based on area
For example table will have
userid | areaname
-----------------
1 |area 1
1 |area 1
2 |area2
2 |area 2
2 |area2
3 |area1
3 |area1
4 |area3
5 |area2
---------------
Result must be
area1 2users
area2 2users
area3 1user
what is the mysql query to achieve this?
Use the Aggregate function COUNT() to get the number of users and GROUP BY to get the count based on areaname
Use DISTINCT for unique values
SELECT COUNT(DISTINCT userid),areaname FROM tablename GROUP BY areaname;
SELECT count(userid),area FROM YOURTABLENAME GROUP BY area;
I see, you can have dublicate entries ad well:
So I would make a sub Select
SELECT sum(partly_sum), area
FROM (
SELECT
userid, area , count(*) as partly_sum
FROM
_YOUR_TABLE_NAME_
WHERE 1
GROUP BY area, userid
) as a_bad_sub_query
WHERE 1
GROUP BY area
Regards
You can use distinct to avoid dupe entries
SELECT COUNT(DISTINCT userid),areaname FROM tablename GROUP BY areaname
I have one table named:
thread_comment
Now the table is getting filled as followed:
thread_comment_id thread_id user_id thread_comment thread_comment_time
1 2 1 This is a comment 2016-09-14 15:30:28
2 4 1 This is a comment 2016-09-14 15:32:28
3 2 1 This is a comment 2016-09-14 15:33:28
4 5 1 This is a comment 2016-09-14 15:34:28
5 7 1 This is a comment 2016-09-14 15:35:28
6 2 1 This is a comment 2016-09-14 15:37:28
7 2 1 This is a comment 2016-09-14 15:40:28
I want to show the newest threads to my page. for example:
as number one i want thread_comment_id 7
as number two i want thread_comment_id 5
I skipped 6 because i don't want any duplicates in the list.
In order to do so i did the folowing:
$sql = "SELECT DISTINCT thread_id FROM thread_comment ORDER BY thread_comment_time DESC"
This is kind of working (Not showing any duplicates). However the order does not make any sense...
For example:
It goes like 5 - 6 -4 - 7 etc...
The column used in the ORDER BY isn't specified in the DISTINCT. You need to use an aggregate function and GROUP BY to make the DISTINCT work.
SELECT DISTINCT thread_id, max(thread_comment_id) FROM thread_comment GROUP BY thread_id ORDER BY max(thread_comment_id) DESC, thread_id
EDIT: added aggregate func max()
Also thread_id is not mandatory in the ORDER BY
It I understand correctly, you want one row per thread. Here is a way to do this:
select tc.*
from thread_comment tc
where tc.thread_date = (select max(tc2.thread_date)
from thread_comment tc2
where tc2.thread_id = tc.thread_id
);
Hi I am using a mysql table "student" which has 4 columns:
Id Name Date StudentId
1 John 2010-01-15 3
2 Matt 2010-01-10 5
3 Jane 2010-02-10 8
4 John 2010-02-11 3
5 Matt 2010-02-11 5
6 Jane 2010-02-11 8
I want to fetch only new entries in the table between 2010-02-10 and 2010-02-12. If a student had a previous entry in the table then the query should not return that value. So in the above case the query should only return both entries of Jane since John and Matt had an entry each previous to the date specified.
This is what I have but it is not working:
SELECT * FROM student
WHERE date(Date)
between '2010-02-10' and '2010-02-12'
and date(Date)
not between '0000-00-00' and '2015-02-09';
GROUP BY and HAVING is what you are looking for if you want single record per student:
SELECT * FROM student
GROUP BY Name
HAVING DATE(Date) BETWEEN '2010-02-10' AND '2010-02-12';
Or I would use subquery if you want all the records:
SELECT * FROM student
WHERE DATE(Date) BETWEEN '2010-02-10' AND '2010-02-12'
AND Name NOT IN
(SELECT DISTINCT Name FROM student WHERE DATE(Date) < '2010-02-10');
How it works:
the subquery selects all the names that have records prior to the date range, i.e. the ones you don't want in your result. It produces set like ('John', 'Matt'). The main query then selects all the records in the given date range where Name NOT IN ('John', 'Matt').
i am facing a very weird problem.
Basically i need to extract a set of rows from a table where every row is the "oldest" in its own group.
The table is structured as follow:
id, integer
domain_id, integer
value, integer
created_at, datetime
My query is
SELECT * FROM domains_urls GROUP BY domain_id HAVING created_at = MAX(created_at)
If i am not wrong, it should group the rows by domain_id and extract the one that it matches created_at = MAX(created_at).
The point is that it does not work as expected!
The table content is
id domain_id value created_at
1 2 1 2014-05-25 10:30:13
2 1 3 2014-05-25 19:30:13
3 2 2 2014-05-25 11:30:13
4 2 7 2014-05-25 15:30:13
5 2 4 2014-05-25 12:30:13
6 2 5 2014-05-25 13:30:13
I should get two rows:
id domain_id value created_at
2 1 3 2014-05-25 19:30:13
4 2 7 2014-05-25 15:30:13
Instead i get only
id domain_id value created_at
4 2 7 2014-05-25 15:30:13
I'm using MySQL 5.5 on Windows 7
I need to use an HAVING+GROUP BY or a DISTINCT+ORDER BY (not tested).
Thanks!
EDIT:
Because i am a dumb (i should avoid working on sunday), the value returned by MAX is related to the table and not to the group!
You can accomplish this by joining the table back to itself using the max(created_at):
select du.*
from domains_urls du
join (select domain_id, max(created_at) maxcreated_at
from domains_urls
group by domain_id
) du2 on du.domain_id = du2.domain_id
and du.created_at = du2.maxcreated_at
SQL Fiddle Demo
Try something like this
Select * from urls as u group by u.id having u.created >= any (select created from urls u2 where u.id == u2.id)
i have not tested this, just wrote that from the top of my head
Using the following query I am looking for a solution to get the latest record that having some conditions.
But it gives me the first record, not the latest. I think its only considering the group by
Please advise me
SELECT * FROM `contacts` WHERE `id_receiver`=1 GROUP BY `id_thread` ORDER BY created DESC
id id_sender id_thread sender_email id_receiver created(datetime)
1 2 2 51 1 2012-03-24 13:44:48
2 4 4 1 5 2012-04-26 13:46:05
3 2 2 51 1 2012-04-09 12:12:30
Required output
id id_sender id_thread sender_email id_receiver created(datetime)
3 2 2 51 1 2012-04-09 12:12:30
I had done a test just swap the order by and group by , giving me an erros.
Anybody can just look in to this?. Thanks.
EDIT Edited question, forget to write id_thread
How can you GROUP BY id_thread when there is no id_thread column in your table?
SELECT *
FROM contacts
WHERE id_receiver = 1
--- GROUP BY id_thread
--- removed
ORDER BY created DESC
LIMIT 1 --- only show one row
Based on your comments, what you want is the latest (ordered by created) row for every id_thread, which is a different and more complex query. There's even a tag for this kind of queries, named [greatest-n-per-group].
SELECT c.*
FROM contacts AS c
JOIN
( SELECT id_thread, MAX(created) AS created
FROM contacts
WHERE id_receiver = 1
GROUP BY id_thread
) AS g
ON (g.id_thread, g.created) = (c.id_thread, c.created)
WHERE c.id_receiver = 1
if records goes sequential than you might SORT by id too -- if and only if it's created in sequential order --