我有USERS
包含以下字段的表_id
name
number_of_posts
我有POSTS
包含以下字段的表_id
user_id
post_text
没有和之间的关系,users
即posts
一个one- to -many
用户有很多帖子
问题是如何更新number_of_posts
inusers
表,使其保持表中的帖子posts
数
更新
我有这些表填充了大约数百条记录,无法使用触发器来更新 number_of_posts 。
users
下面给出的示例脚本显示了如何通过同时加入和posts
表使用来获取与用户关联的帖子数,LEFT OUTER JOIN
然后在用户GROUP BY
表中的 *_id* 字段上使用以获取帖子数。
询问:
CREATE TABLE users
(
_id INT NOT NULL
, name VARCHAR(30) NOT NULL
);
CREATE TABLE posts
(
_id INT NOT NULL
, _userid INT NOT NULL
, name VARCHAR(30) NOT NULL
);
INSERT INTO users (_id, name) VALUES
(1, 'user 1'),
(2, 'user 2'),
(3, 'user 3');
INSERT INTO posts (_id, _userid, name) VALUES
(1, 1, 'post 1'),
(2, 1, 'post 2'),
(3, 2, 'post 3');
SELECT u._id
, u.name
, COUNT(p._id) number_of_posts
FROM users u
LEFT OUTER JOIN posts p
ON u._id = p._userid
GROUP BY u._id;
输出:
_ID NAME NUMBER_OF_POSTS
--- ------ ---------------
1 user 1 2
2 user 2 1
3 user 3 0
作为一次性更新,试试这个,但触发解决方案是保持最新状态的正确方法:
UPDATE users AS u SET u.number_of posts = (SELECT COUNT(*) FROM posts AS p WHERE p.user_id=u.user_id)
您可以使用帖子表上的触发器来执行此操作。每次插入帖子时,更新 users 表上的 number_of_posts。
见http://dev.mysql.com/doc/refman/5.6/en/triggers.html
更新:完整的工作解决方案
drop table if exists users;
create table users (
_id bigint unsigned auto_increment primary key,
name varchar(50) not null,
number_of_posts integer not null default 0
);
drop table if exists posts;
create table posts (
_id bigint unsigned auto_increment primary key,
user_id bigint unsigned not null,
post_text text
);
-- Populate with dummy data
insert into users (name) values ('Bob'), ('Sally');
insert into posts (user_id, post_text)
values (1, 'First!!'), (1, 'Second...'),
(2, 'Post 1'), (2, 'another post'), (2, 'more posts');
-- One-time update of users table
update users u
set u.number_of_posts = (
select count(0) from posts p
where u._id = p.user_id
);
-- trigger to keep post count up to date when future posts are made
drop trigger if exists trg_post_count;
delimiter $$
create trigger trg_post_count
after insert on posts
for each row
begin
select count(0) into @post_count
from posts
where user_id = NEW.user_id;
update users
set number_of_posts = @post_count
where _id = NEW.user_id;
end;
$$
delimiter ;
-- test trigger
insert into posts (user_id) values (2);
select * from users;
正如 dwurf 建议的那样,我绝对建议将其放入触发器中以保持该字段的最新状态。但是,我完全不同意他的观点,即它应该只是一个您在每次更新时增加的数字。这很脆弱,容易出错。您应该使用以下查询来确定每个用户有多少帖子:
update
users
set
number_of_posts = (
select
count(0)
from
posts p
where
p.user_id = users.id
)
;