2

我有USERS包含以下字段的表_id name number_of_posts

我有POSTS包含以下字段的表_id user_id post_text

没有和之间的关系,usersposts一个one- to -many用户有很多帖子

问题是如何更新number_of_postsinusers表,使其保持表中的帖子posts

更新

我有这些表填充了大约数百条记录,无法使用触发器来更新 number_of_posts 。

4

4 回答 4

2

users下面给出的示例脚本显示了如何通过同时加入和posts表使用来获取与用户关联的帖子数,LEFT OUTER JOIN然后在用户GROUP BY表中的 *_id* 字段上使用以获取帖子数。

单击此处查看 SQL Fiddle 中的示例。

询问:

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
于 2012-04-29T14:58:33.057 回答
1

作为一次性更新,试试这个,但触发解决方案是保持最新状态的正确方法:

UPDATE users AS u SET u.number_of posts = (SELECT COUNT(*) FROM posts AS p WHERE p.user_id=u.user_id)
于 2012-04-29T14:55:58.580 回答
1

您可以使用帖子表上的触发器来执行此操作。每次插入帖子时,更新 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;
于 2012-04-29T14:43:25.437 回答
0

正如 dwurf 建议的那样,我绝对建议将其放入触发器中以保持该字段的最新状态。但是,我完全不同意他的观点,即它应该只是一个您在每次更新时增加的数字。这很脆弱,容易出错。您应该使用以下查询来确定每个用户有多少帖子:

update
  users
set 
  number_of_posts = ( 
    select
      count(0)
    from
      posts p
    where
      p.user_id = users.id
    )   
; 
于 2012-04-29T14:57:07.940 回答