Reputation: 4099
Consider the following tables:
users messages
----------------- -----------------------
user_id messages msg_id user_id content
----------------- -----------------------
1 0 1 1 foo
2 0 2 1 bar
3 0 3 1 foobar
4 3 baz
5 3 bar
I want to count the number of messages per user and insert the outcome into users.messages, like this:
users
-----------------
user_id messages
-----------------
1 3
2 0
3 2
I could use PHP to perform this operation, pseudo:
foreach ($user_id in users) {
$count = select count(msg_id) from messages where user_id = $user_id
update users set messages = $count
}
But this is probably very inefficient as compared to one query executed in MySQL directly:
UPDATE users SET messages = (
SELECT COUNT(msg_id) FROM messages
)
But I'm sure this is not a proper query. Therefore, any help would be appreciated :-)
Upvotes: 2
Views: 1667
Reputation: 1963
Here's the answer:
UPDATE `users` AS u
SET u.messages=(SELECT COUNT(*) FROM messages WHERE user_id=u.user_id)
and the test:
http://sqlfiddle.com/#!2/2768b/1
I just hope these are not huge tables or this could take a while...
UPDATE: Removed unnecessary JOIN from the query Thanks to @Ariel and @Zane Bien for correcting my answer!
Upvotes: 3
Reputation: 860
This one would surely work. Try this:
UPDATE users u
SET u.messages =
( SELECT COUNT (*)
FROM messages m
GROUP BY user_id
HAVING u.user_id = m.user_id);
Upvotes: 1
Reputation: 23125
MySQL permits you to use JOIN
operations in UPDATE
statement like so:
UPDATE
users a
LEFT JOIN
(
SELECT user_id, COUNT(1) AS messagecount
FROM messages
GROUP BY user_id
) b ON a.user_id = b.user_id
SET
a.messages = COALESCE(b.messagecount, 0)
What this will do is line up each corresponding user with the count of his/her messages in the messages
table, and so updating the messages
column becomes a simple matter of referencing the corresponding joined column containing the message count.
If a user does not have any messages in the messages
table, it will simply set the column to 0
.
You can also be sure that this will execute very quickly as there is no need to use inefficient subqueries(which end up executing on each iteration), and also the fact that the join will be performed over indexes.
Upvotes: 1
Reputation: 2306
Assuming you know how to fire the query i'd say this ...
Create a trigger on insert whenever an message is posted into the messages table and insert the number of rows into the users table. Thus you don't have to fire a query by php each time you insert a new message. Thus your no of messages will be updated automatically whenver you insert a new message and you just have to fire a select query when you want to check the number of messages for a particular user.
Upvotes: 1
Reputation: 26753
UPDATE users JOIN
(SELECT user_id, COUNT(msg_id) num FROM messages group by user_id) c
USING (user_id)
SET users.messages = c.num
Note: I didn't test this.
Upvotes: 1
Reputation: 13465
Try this::
UPDATE users u
inner join
(
Select user_id, count(1) as number
from users u inner join messages m on (u.user_id=m.user_id) group by m.user_id
) as temp_message tm on (u.user_id=tm.user_id)
set u.messages=tm.number
Upvotes: 0