NOTE: Yes, there are many similar questions to this one. I would not bother posting a new question if any of them helped me understand how to correct my query.
This is a basic MySQL threaded messaging project, with 3 tables: messages
, messages_people
, and people
. Each message can have multiple people attached to it. Each person can have multiple messages.
messages < messages_people > people
I'm looking for a single query that returns a list of THREADS (not all messages, just the last message in each thread a person is a part of), with a bunch of information about the LAST message in each thread. The following schema and data ...
http://sqlfiddle.com/#!9/f724ca/8
... includes a query that selects the correct rows (with only a few fields, for brevity) for a particular person (person_id
= 1). Note: Change person_id
to see other results.
Prior to MySQL 5.7, the following query would show the most recent message (highest id) in any thread a single person was a part of:
SELECT m.`id`, m.`thread_id`, m.`message`
FROM `messages_people` AS mp
LEFT JOIN `messages` AS m ON (m.`id` = mp.`message_id`)
WHERE mp.`person_id` = 1
GROUP BY m.`thread_id`
ORDER BY mp.`id` DESC;
But MySQL 5.7 changed how GROUP BY works in a way I don't yet understand. None of the online explanations show any before/after examples, which is how I learn best. The following query does work ...
SELECT m.`id`, m.`thread_id`, m.`message`
FROM `messages` AS m
WHERE m.`id` IN (
SELECT MAX(m.`id`) AS `id`
FROM `messages` AS m
WHERE m.`thread_id` IN (
SELECT DISTINCT(m.`thread_id`)
FROM `messages_people` AS mp
LEFT JOIN `messages` AS m ON (m.`id` = mp.`message_id`)
WHERE mp.`person_id` = 1
)
GROUP BY m.`thread_id`
);
... however the idea of so many nested queries makes me vomit in my mouth a little. It's clearly neither correct nor performance-efficient.
I know I can tweak my.cnf
to get pre 5.7 GROUP BY
functionality by setting sql_mode=only_full_group_by
to sql_mode=''
, but I'd rather learn the correct approach than be forced to write unportable code.
What's the correct way of using GROUP BY with ORDER BY in a single query with MySQL 5.7?