更新字段从另一个表顺序获取值

时间:2013-10-04 11:52:23

标签: mysql insert sql-update

鉴于这些表没有先前的关系:

*codes*            *people*
id label        id type code_id
1    1          1   2     X
2    1          2   2     X
3    1          3   7     X
4    2
5    2

我想更新表peoplecodes表中选择值。我需要来自people label=2 {{}}}的每个项目与codes的ID不同。由于代码多于人,因此不会有人共享代码。

所以例如结果是

   *people*
id type code_id
1   2     4       # updated with one value from codes table
2   2     5       # updated with another value from codes table
3   7     X       # not updated, as type<>2

我已对此进行了测试,但在使用WHERE过滤器时无效:

UPDATE people A
INNER JOIN
  (SELECT id FROM codes WHERE label=2) B
USING (id)
SET A.code_id=B.id
WHERE A.type=2;

我做错了什么?


对于那些检查问题的人,我准备了要在SQL Fiddle中测试的代码,如下所示:

CREATE TABLE codes (id int auto_increment primary key, label int);
CREATE TABLE people (id int auto_increment primary key, type int, code_id int);
INSERT INTO codes VALUES (1,1),(2,1),(3,1),(4,2),(5,2);
INSERT INTO people (id,type) VALUES (1,2),(2,2),(3,7);

2 个答案:

答案 0 :(得分:1)

您可以使用CURSORs让它工作(这样您就可以逐行遍历代码表复制结果)。像这样:

CREATE PROCEDURE updatecodes()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE a,b INT;
DECLARE cur1 CURSOR FOR SELECT id FROM codes WHERE label = 2;
DECLARE cur2 CURSOR FOR SELECT id FROM people WHERE type = 2;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;


OPEN cur1;
OPEN cur2;

read_loop: LOOP
  FETCH cur1 INTO a;
  FETCH cur2 INTO b;
  IF done THEN 
    LEAVE read_loop;
  END IF;

  UPDATE people SET code_id = a WHERE id = b;
END LOOP;

CLOSE cur1;
CLOSE cur2;

END

然后只是

CALL updatecodes();

如果我有链接权限,那么应该有一个更新的SQL小提琴:SQL Fiddle

答案 1 :(得分:1)

您也可以这样做......

 SELECT x.id,x.type, y.id code_id
   FROM 
      ( SELECT a.*
             , COUNT(*) rank
          FROM people a
          JOIN people b
            ON b.type = a.type
           AND b.id <= a.id
         GROUP  
            BY type, id
      ) x
   JOIN 
      ( SELECT a.*
             , COUNT(*) rank
          FROM codes a
          JOIN codes b
            ON b.label = a.label
           AND b.id <= a.id
         GROUP  
            BY label
             , id
      ) y
     ON y.label = x.type 
    AND y.rank = x.rank; 

...或重写为更新......

 UPDATE people p
   JOIN
      ( SELECT a.*
             , COUNT(*) rank
          FROM people a
          JOIN people b
            ON b.type = a.type
           AND b.id <= a.id
         GROUP  
            BY type, id
      ) x
     ON x.id = p.id
   JOIN 
      ( SELECT a.*
             , COUNT(*) rank
          FROM codes a
          JOIN codes b
            ON b.label = a.label
           AND b.id <= a.id
         GROUP  
            BY label
             , id
      ) y
     ON y.label = x.type 
    AND y.rank = x.rank
    SET p.code_id = y.id;