Mysql 通过对表本身执行查询来更新表

Mysql 通过对表本身执行查询来更新表,mysql,sql,Mysql,Sql,我想根据从自身选择的查询更新表。从这样的表格开始: __________________________ | id | uid | uid_seq_no | -------------------------- | 1 | a | NULL | | 2 | a | NULL | | 3 | b | NULL | | 4 | a | NULL | | 5 | b | NULL | | 6 | b

我想根据从自身选择的查询更新表。从这样的表格开始:

__________________________
| id | uid |  uid_seq_no |
--------------------------
| 1  | a   |     NULL    |
| 2  | a   |     NULL    |
| 3  | b   |     NULL    |
| 4  | a   |     NULL    |
| 5  | b   |     NULL    |
| 6  | b   |     NULL    |
| 7  | a   |     NULL    |
| 8  | c   |     NULL    |
--------------------------
我想将uid_seq_no更新为作用域为uid的行的序列号,这样最终结果将是:

__________________________
| id | uid |  uid_seq_no |
--------------------------
| 1  | a   |       1     |
| 2  | a   |       2     |
| 3  | b   |       1     |
| 4  | a   |       3     |
| 5  | b   |       2     |
| 6  | b   |       3     |
| 7  | a   |       4     |
| 8  | c   |       1     |
--------------------------
我已尝试执行以下查询:

UPDATE keySeq a
  SET uid_seq_no=(
    SELECT IFNULL(uid_seq_no,0)+1 FROM keySeq b
      WHERE a.uid = b.uid AND uid_seq_no IS NOT NULL
      ORDER BY id
      LIMIT 1
    );
但我得到:表“a”被指定了两次,既作为“更新”的目标,也作为数据的单独源

我还尝试执行它,如:

UPDATE keySeq a
  SET uid_seq_no=(
    SELECT n FROM (
      SELECT IFNULL(uid_seq_no,0)+1 AS n FROM keySeq b
        WHERE a.uid = b.uid AND uid_seq_no IS NOT NULL
        ORDER BY id
        LIMIT 1
      ) AS T
    )
但是我在where子句中得到了未知的列a.uid。可能是因为子查询无法访问查询范围

现在我没有主意了


示例表:

您可以使用此查询:

UPDATE keySeq
left join  (
  select a.id, (SELECT count(1) + 1 FROM keySeq b 
                     where b.uid = a.uid and  b.id<a.id) Rank
  from keySeq a
) xQ on xQ.Id=keySeq.id
SET keySeq.uid_seq_no=xQ.Rank;

为更新设置秩值的备选方案:

SELECT 
id
, uid
, uid_seq_no
, ( 
  CASE uid
  WHEN @vUid
  THEN @vRank := @vRank + 1 
  ELSE @vRank := 1 AND @vUid := uid END
) + 1 AS rank

FROM keySeq,
(SELECT @vRank := 0, @vUid := '') var
ORDER BY uid, id

您可以使用函数rownumber。这是按uid分区的,如下所示。一个选择是这样的:

SELECT id, uid
      ,ROW_NUMBER() OVER (PARTITION BY uid ORDER BY id, uid ASC) [uid_seq_no]
  FROM keySeq
ORDER BY id
要在update语句中使用select,可以使用列别名来消除更新的歧义:

UPDATE keySeq
   SET uid_seq_no = dT.uid_seq_no2

  FROM ( SELECT id [id2] --I use column alias here and for uid_seq_no2
        ,uid
        , ROW_NUMBER() OVER (PARTITION BY uid ORDER BY id, uid ASC) [uid_seq_no2]
          FROM keySeq K1
       ) AS dT

 WHERE id = dT.id2
下面是我用来测试的SQLFIDLE: