This question already has answers here:
Select first row in each GROUP BY group?
(20 answers)
Closed 4 years ago.
I have two tables: companies and emails.
I would like to select the last email of every company
I tried this:
SELECT *
FROM companies
LEFT
JOIN emails
ON companies.company_id = emails.company_id
WHERE companies.status = 'active'
GROUP
BY emails.company_id
ORDER
BY emails.date DESC;
But this doesn't work, the ORDER BY part should somehow precede the GROUP BY part, because I want to get the last email of every company, not sort the end results.
Can someone help me?
Thanks.
UPDATE
I ended up doing this:
SELECT *
FROM companies
LEFT
JOIN (
SELECT company_id, date
FROM emails
ORDER
BY date DESC
) emails
ON companies.company_id = emails.company_id
WHERE companies.status = 'active'
GROUP
BY emails.company_id;
Thank you for the help.
If I understand your problem the right way, I think something like that could work.
SELECT * FROM companies c
LEFT JOIN emails e ON c.company_id = e.company_id
AND (e.company_id, e.date) IN (
SELECT company_id, max(date) FROM emails GROUP BY company_id
)
WHERE c.status = 'active';
EDIT : Update with Thorsten answer
Related
This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 2 years ago.
I have database to store customer and messages
I am trying to get list of all the customer and their latest messages like first screen in messenger.
SELECT *
FROM message AS m
LEFT JOIN customer AS c ON c.id=m.sender_id
ORDER BY m.sent_at DESC
but this returns all the message for all user. I've also tried doing this
SELECT *
FROM message AS m
LEFT JOIN customer AS c ON c.id=m.sender_id
GROUP BY c.id
but this doesn't run on all databases and cannot sort result set to get latest messages only.
One option uses row_number(), available in MySQL 8.0:
select * -- better enumerate the columns you want here
from customer as c
left join (
select m.*, row_number() over(partition by m.sender_id order by sent_at desc) rn
from messages m
) m on on c.id = m.sender_id and m.rn = 1
order by m.sent_at desc
This gives you the last message per customer. You can change the condition on rn if you want more messages (rn <= 3 would give you three messages per customer).
Note that I changed the order of the tables in the left join, so it allows customers without messages (rather than messages without customers, which probably does not make sense).
If you are running an earlier version, than an alternative is to filter with a subquery:
select * -- better enumerate the columns you want here
from customer as c
left join messages m
on m.sender_id = c.id
and sent_at = (select min(m1.sent_at) from messages m1 where m1.sender_id = m.sender_id)
For perforamnce with the correlated subquery, consider an index on (sender_id, sent_at) (ideally, there should be no duplicates in these columns).
This question already has answers here:
Retrieving the last record in each group - MySQL
(33 answers)
Closed 3 years ago.
I'm coding a message system using mysql.
Everything works fine when I list users whom I'm conversing with, until I want to add date of the last or the start of conversation.
When I add a.date I get duplicate results when the date isnt the same.
Here is my sqlfiddle
Since, you were pulling only user_id then in both cases (send/recieve) it was giving you distinct record. But now with date it is no more distinct. you need to do something like:
SELECT temp.id_user, MAX(temp.date) as date
FROM
(
SELECT users.id_user,
a.date
FROM users
LEFT JOIN message AS a
ON users.id_user = a.id_user_recipient
LEFT JOIN message AS b
ON a.id_user_recipient = b.id_user_sender
WHERE a.id_user_sender = 1
UNION DISTINCT
SELECT users.id_user,
a.date
FROM users
LEFT JOIN message AS a
ON users.id_user = a.id_user_sender
LEFT JOIN message AS b
ON a.id_user_sender = b.id_user_recipient
WHERE a.id_user_recipient = 1
) as temp
GROUP BY temp.id_user;
Grabbing max(date) will ensure to return only one record as with group by
This question already has answers here:
Select all records don't meet certain conditions in a joined table
(2 answers)
Closed 5 years ago.
i am having two tables in my DB like members and payments . Table Members has the name and id of users and payment table has the id,amount and session of payments like if user 1 has paid 1500 for a session 3 then table payment has the following details. mid 1, session 3 and amount 1500.
Now i want to fetch the names of all the users which have not aid for session 1
i am using the following query but it is not working
SELECT NAME
,id
FROM member m
,payment p
WHERE (
p.session = '3'
AND m.id != p.mid
)
This is not giving me the required result please help me .
What about something like this:
SELECT NAME
,id
FROM member m
inner JOIN payment paid
ON m.id = paid.mid
AND paid.sessionid = '1'
LEFT JOIN payment p
ON m.id = p.mid
AND p.sessionid = '3'
WHERE p.id IS NULL
When you want to get data from more than 2 tables , you have to use join and if you don't want to use join as you are doing, then make sure you have exact relation between that tables, e.g a.id = b.membe_id etc..
And in your case, i think the relation is not right, make sure you have something common in two tables.
Thanku.
This question already has answers here:
What is the difference between "INNER JOIN" and "OUTER JOIN"?
(28 answers)
Closed 8 years ago.
Im doing the follwing, to create an user report
SELECT b.username, b.name, b.permissiontoedit, a.total, a.user
FROM (SELECT user, Count( * ) AS total
FROM products
GROUP BY user)a
JOIN user b ON a.user = b.username
This should give a table with the username, full name, permision (1/0) and the total of entries.
Sadly, the query does only list users, which made more 1 or more entries in the table products. But i want all users, and if the have not made any entries in products it should display 0 or nothing.
where do i made a mistake?
Using a LEFT JOIN you can get your result:
SELECT
u.username, u.name, u.permissiontoedit, COUNT(p.user) as total
FROM
user u
LEFT JOIN
products p
ON
u.username = p.user
Note: COUNT(expression) counts only NOT NULL rows in contrast to COUNT(*) that counts every row.
I have a mysql DB with two tables:
messages
message_answers
I'd like to fetch all messages and the number of answers for each of them, like:
first message (10 answers)
second message (5 answers)
Is it possible with a single sql query ?
I tried a query and a subquery for the count, but I don't know how to have the current id from the main query to make the "WHERE" restriction on the subquery (like: "message_answers.message_id = messages.id").
Thank you,
Sébastien
SELECT m.message, COUNT(ma.answer_id) AS AnswerCount
FROM messages m
LEFT JOIN message_answers ma
ON m.id = ma.message_id
GROUP BY m.message
select m.id, count(ma.id)
from messages m
join join message_answer ma on ma.id = m.message_id
group by 1