My table for message inbox concept email is a primary in the table. I want to get the last message which is sent by particular email.
tbl_msg:
id
email
msg
Example Data:
Id email msg
1 xyz#gmail.com This is test
2 abc#gmail.com All is well
3 xyz#gmail.com This is test2
I want to get the last appearance of each email and msg
Id email msg
2 abc#gmail.com All is well
3 xyz#gmail.com This is test2
What I tried:
SELECT cnote.`id`,cnote.`email`,cnote.`msg` FROM `tbl_msg` cnote inner join (select distinct email,id from client_com group by email) as note
on cnote.id=note.id
Guide me if I wrong
Use This query:
SELECT m1.* FROM tbl_msgs m1 LEFT JOIN tbl_msgs m2 ON (m1.email = m2.email AND m1.id < m2.id) WHERE m2.id IS NULL;
This will join with the same table and with condition m1.id < m2.id , will get the latest one.
Another option is using subquery:
SELECT * FROM tbl_msgs WHERE id IN (SELECT MAX(id) FROM tbl_msgs GROUP BY email);
To get the latest messsage for each email address in the table you do not need a JOIN, you just need to ORDER and GROUP BY:
SELECT `id`, `email`, `msg`
FROM `tbl_msg`
GROUP BY `email`
ORDER BY `id` DESC
You can use this query:
SELECT id, email, msg FROM you_table
GROUP BY email
ORDER BY id DESC
With this one you will have only 1 row per email, and you'll have the last because is ordered by id DESC.
If you are running a PDO connection (The way I know to do it, not sure if there is a MySQLi way)
$theLastIdGiven = $handlerDbConnection->lastInsertId();
Or if you want to run it through a query, and get the last result, just add ORDER BY id DESC LIMIT 0, 1 and that will order the data by id in a descending form then get the first bit of data :)
Hope this helped you!
SELECT ID, email, Msg FROM tbl_msg WHERE ID IN (
(SELECT MAX(ID) FROM tbl_msg GROUP BY email))
Related
I want to show the message list like facebook messenger where in left corner you can see all the message you make.
user_table
user_id
user_firstname
user_latsname
message_table
message_id
message_user_id
message_to_user_id
message_content
message_time_stamp
My SQL
SELECT user_table.user_id,
CONCAT(user_table.user_firstname,' ',user_table.user_lastname) AS user_fullname,
message_table.message_user_id,
message_table.message_content,
message_table.message_time_stamp
FROM user_table
INNER JOIN message_table
ON user_table.user_id = message_table.message_user_id
WHERE (message_table.message_to_user_id = '$session')
ORDER BY message_table.message_time_stamp DESC
My code works fine if someone message me first.
It show in my message list that someone message me.
But when i'm the one who make the first message.
It doesn't show in my message list.
He should reply in my message before i can see it in my message list.
But i want to show when someone message me and when i'm the one who make the first message.
message_table with sample data
user_table with sample data
result
But when i add new user in the user_table and message him. it will not show in my Message List.
I want my expected result is when i message new user it will show in my message list
your line (in sql query)
message_table.message_to_user_id = '$session'
is probably the reason, why you don't see the messages you send yourself (since you are not the recipient)
to fetch all messages you're involved in, it should probably be:
message_table.message_to_user_id = '$session' or message_table.message_user_id = '$session'
I hope $session is not user-provided, or you've got some possible sql-injection at hand ;o)
SOLUTION
SELECT user_id, user_fullname, message_content
FROM
(
(SELECT user_table.user_id,
CONCAT(user_table.user_firstname,' ',user_table.user_lastname) AS user_fullname,
message_table.message_user_id,
message_table.message_content,
message_table.message_time_stamp
FROM user_table
INNER JOIN message_table
ON user_table.user_id = message_table.message_to_user_id
WHERE (message_table.message_user_id = '$session')
)ORDER BY message_time_stamp DESC
UNION DISTINCT
(SELECT user_table.user_id,
CONCAT(user_table.user_firstname,' ',user_table.user_lastname) AS user_fullname,
message_table.message_user_id,
message_table.message_content,
message_table.message_time_stamp
FROM user_table
INNER JOIN message_table
ON user_table.user_id = message_table.message_user_id
WHERE (message_table.message_to_user_id = '$session')
)ORDER BY message_time_stamp DESC
) as id GROUP BY user_id ORDER BY message_time_stamp DESC
Here's the solution what i made in my problem. I made 2 select statement where the first select only select where i'm the one who makes the first message and the second select statements select where someone first message me. And then i Union it.
I have db with few 1000 of contacts and would like to delete all duplicated records. Sql query I have at the moment works well ( when in records - tel, email, name1 are duplicated). Query deletes duplicates with lower id then last occurring record. But in some cases another fields of the record a filled in already (important ones will by title and name2). What i would like to achieve is for mysql to check if these fields are filled in and keep only the record with most information filed in.
My Query
<?php
$del_duplicate_contacts = $mysqli->query("
DELETE ca
FROM contacts ca
LEFT JOIN
(
SELECT MAX(id) id, name1, tel, email
FROM contacts
GROUP BY name1, tel, email
) cb ON ca.id = cb.id AND
ca.name1 = cb.name1 AND
ca.tel = cb.tel AND
ca.email = cb.email
WHERE cb.id IS NULL
");
?>
Example of table:
ID title name1 name2 tel email
1 John 01234 1#1.com
2 Mr John Smith 01234 1#1.com
3 John 01234 1#1.com
My query will delete record 1 and 2. I would like to keep only nr 2 and delete 1 and 3.
How I can achieve that? Is is possible? Or maybe i should involve PHP, if so How?
Use order by in group_concat, you can try this:
DELETE c1 FROM contacts c1
JOIN (
SELECT
substring_index(group_concat(id ORDER BY ((title IS NULL OR title ='') AND (name2 IS NULL OR name2 = '')), id DESC), ',', 1) AS id,
name1, tel, email
FROM contacts
GROUP BY name1, tel, email
) c2
ON c1.name1 = c2.name1 AND c1.tel = c2.tel AND c1.email = c2.email AND c1.id <> c2.id;
Demo Here
I have got solution using NOT EXIST clause instead of NOT IN
DELETE FROM contacts
WHERE NOT EXISTS (
SELECT 1 FROM (
SELECT * FROM (
SELECT * FROM contact AS tmp ORDER BY title DESC, name1 DESC, name2 DESC, email DESC, tel DESC )
as tbl group by name1)
as test WHERE contact.id= test.id
)
OOPS - This is the worst answer I have produced so far -- warning the top bit is dangerous, not sure why I did not include any group -- please continue to the bottom part, which is working now:
DELETE FROM contacts WHERE ID IN (
SELECT ID FROM (
SELECT DISTINCT a.ID
FROM contacts AS a
JOIN contacts AS b
ON a.name1 = b.name1
AND a.tel = b.tel
AND a.email = b.email
ORDER BY a.name1 DESC, a.name2 DESC, a.title DESC
LIMIT 1,100000
) AS tmp
)
LIMIT Must be 1, xxxx -- not 0, xxxx to keep the first one undeleted
As you cannot delete directly from the same table found in sub-query, just add a mask layer, so it is now tested working
Before Deleting, always double check what is going to be deleted:
SELECT * FROM contacts WHERE ID IN (
SELECT ID FROM (
SELECT DISTINCT a.ID
...
LIMIT 1,100000
) AS tmp
)
Apologies for the damage, luckily you did on a testing db
=====================================
Now here is the correct solution:
Let's check what is in the testing table:
According to question, we noticed only #2 #4 #5 is good to keep. And here is the result:
And we want to delete any records not in above list, before delete, we double check what is going to be deleted:
And we are ready to delete:
And here is the SQL, make sure you do on testing db first:
DELETE FROM contacts WHERE ID NOT IN (
SELECT * FROM (
SELECT ID FROM (
SELECT * FROM contacts ORDER BY title DESC, name1 DESC, name2 DESC, tel DESC, email DESC
) AS tmp
GROUP BY name1, tel, email
) AS del
)
This query will work without any ordering options !
DELETE FROM contacts where ID NOT IN (
SELECT ID FROM ( Select A.ID from contacts as A
join contacts AS B
ON A.name1 = B.name1
AND A.name2 = B.name2
AND A.tel = B.tel
AND A.email = B.email) As mytry);
Hi I have a table like this
ID UserName
1 test#test.com
2 test#test.com
3 john#stack.com
4 test#test.com
5 adam#stack.com
6 john#stack.com
I need an output like this. I need only repeated rows list. How can I create this kind of an output using mysql query.
ID UserName Count
1 test#test.com 3
2 john#stack.com 2
Please help me.
Thanks.
I had the same problem some time ago and solved it like this (as far as I remember):
SELECT *
FROM tableA INNER JOIN
(SELECT DISTINCT MAX(id) as id, type_id, temp FROM tableA GROUP BY type_id, temp) AS t
ON tableA.id = t.id
AND tableA.type_id = t.type_id
AND tableA.temp = t.temp
You join the table with itself selecting the ids that are duplicate. The fields that should be tested against duplicate values are in this case type_id and temp. If you need more or less fields that should be considered as duplicates you can adjust the fields.
I don't know if this helps in your case and if it can be done in a more simple way, so I'm prepared for downvotes ;-)
Edit: removed last condition AND tableA.id < t.id as suggested by ypercube because it leads to 0 results.
It looks like you're trying to pull the following data:
First ID for a given UserName
The UserName itself
The total number of IDs for that UserName
This query should do the trick:
SELECT
MIN(id),
UserName,
COUNT(id)
FROM users
GROUP BY UserName;
since the ID is not unique so its a bit not logical to get the sum of unique UserName from the table.
If the ID is not required we can get the result from single query.
SELECT UserName, COUNT(UserName) AS Count
FROM TableName GROUP BY UserName
HAVING COUNT(UserName) > 1;
But in the case of ID in the result it will be a more complicated query including sub-query and inner table.
SELECT UserName
, COUNT(*) AS `Count`
FROM tableX
GROUP BY UserName
HAVING COUNT(*) > 1
Hi this is the right answer.
SELECT UserName, COUNT(UserName) AS Count
FROM TableName GROUP BY UserName
HAVING COUNT(UserName) > 1;
I have a sample database like this, in which, id is always unique, but the user_id is not unique.
id,user_id,message,msg_datetime
111,u1, msg from u1,time present here
112,u2, msg from u2,time present here
113,u3, msg from u3,time present here
114,u2, msg from u2,time present here
115,u7, msg from u7,time present here
116,u2, msg from u2,time present here
117,u1, msg from u1,time present here
118,u5, msg from u5,time present here
so i want to grab only those unique users who have messaged and order them in DESC by msg_datetime.
This is the query i have.
select id,DISTINCT user_id,msg_datetime ORDER BY msg_datetime DESC but i am getting an error as:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DISTINCT. any help here? what is the correct syntax for what i am trying to achieve?
I want to show only one entry for each user, it does not matter which ID i am showing but only 1 per user.
If you don't care which record with the same user_id query should return, then
SELECT id,user_id,msg_datetime FROM table_1 GROUP BY user_id ORDER BY msg_datetime DESC
If you want to display, for instance, the last record for each user, you need
SELECT a.user_id, a.last_time, b.id
FROM
(SELECT user_id, MAX(msg_datetime) as last_time
FROM table1)a
INNER JOIN table1 b ON (b.user_id = a.user_id AND b.msg_datetime = a.last_time)
ORDER BY a.last_time;
SELECT syntax:
SELECT (fieldlists)
FROM (table)
[WHERE (conditions)]
ORDER BY (something)
You kindof forgot to say which table you want the data from.
You misunderstand how DISTINCT works. It works on rows not fields. What you want is a groupwise maximum, also known as greatest-n-per-group.
Here's one way to do it in MySQL:
SELECT id, user_id, message, msg_datetime
FROM (
SELECT
id, user_id, message, msg_datetime,
#rn := CASE WHEN #prev_user_id = user_id
THEN #rn + 1
ELSE 1
END AS rn,
#prev_user_id := user_id
FROM (SELECT #prev_user_id := NULL) vars, Table1 T1
ORDER BY user_id, msg_datetime DESC
) T2
WHERE rn = 1
ORDER BY msg_datetime
I currently have a MySQL SELECT statement that pulls information from two tables to display a "Sent Messages" field for private messaging.
I'd like to know how I can do add a COUNT to my query to count the number of "receivers" in one thread.
Here's the basic gist of my table structure, (NOTE: the relational tie between the two tables is the 'message-id' in pm-info and the "id" in pm_data):
pm_info:
id message_id receiver_id is_read read_date
pm_data:
id date_sent title sender_id thread_id content
Here's my SELECT Statement:
SELECT pm_info.is_read, group_concat(DISTINCT receiver.usrFirst) as receiver_name,
pm_data.date_sent, pm_data.title, pm_data.thread_id, pm_data.id as data_id,
MAX(date_sent) AS thread_max_date_sent
FROM pm_info
INNER JOIN pm_data ON pm_info.message_id = pm_data.id
INNER JOIN tblUsers AS receiver ON pm_info.receiver_id = receiver.usrID
WHERE pm_data.sender_id = '$usrID'
GROUP BY pm_data.thread_id
ORDER BY thread_max_date_sent DESC
And it ouputs the recipients like this:
Message 1 - Recipients: John, David, Steve - thread_id = 1234
Message 2 - Recipients: Bill, David, John, Ed, Steve - thread_id = 1345
Basically, what I'd like to do is have the option to COUNT the recipients, so in the example above, "Message 1" would display three (3) recipients, and "Message 2" would display five (5) recipients.
This way, if I have a thread/message that was sent to 30 users, not all thirty names will be printed out.
Thanks!
Have you tried just replacing GROUP_CONCAT with COUNT? Like this:
COUNT(DISTINCT receiver.usrFirst) as receiver_count
Or better, use pm_info.receiver_id as in (which could potentially let you eliminate one of your joins):
COUNT(DISTINCT pm_info.receiver_id) as receiver_count
You could use a subquery to select up to 3 recipients per message, and then another subquery to concatenate their names:
select
( select group_concat(usrFirst separator ', ')
from tblUsers
where usrId in (
select usrId
from tblUsers
where usrId = pm_info.receiver_id
limit 3
)
) as receiver_name
from pm_info
....
You could move the count and group_concat into a concat statement.
... group_concat(DISTINCT receiver.usrFirst) as receiver_name ...
becomes
... concat('messages:', count(distinct receiver.usrFirst),'(',group_concat(DISTINCT receiver.usrFirst),')') as receiver_name ...