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

时间:2017-11-09 20:41:21

标签: mysql sql

我想根据从中选择的查询来更新表。从这样的表开始:

__________________________
| 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
    );

但我明白了:Table 'a' is specified twice, both as a target for 'UPDATE' and as a separate source for data

我也尝试过执行它:

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
    )

但我得Unknown column 'a.uid' in 'where clause'。可能是因为子子查询无法访问查询范围。

现在我没有想法。

示例表:http://sqlfiddle.com/#!9/e3f3b6/1

3 个答案:

答案 0 :(得分:2)

您可以使用此查询:

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;

答案 1 :(得分:0)

替代设置更新的排名值:

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

答案 2 :(得分:0)

您可以使用函数rownumber。这由uid分区,如下所示。选择就像这样:

SELECT id, uid
      ,ROW_NUMBER() OVER (PARTITION BY uid ORDER BY id, uid ASC) [uid_seq_no]
  FROM keySeq
ORDER BY id

要在更新语句中使用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

以下是我用来测试它的sqlfiddle:http://sqlfiddle.com/#!6/c5bae/1