如何在mysql中添加没有光标的顺序号?

时间:2017-07-21 00:15:10

标签: mysql stored-procedures

我有一个表可以有一些有效的重复值,所以我需要一个额外的列,其中包含所述副本的外观序列号,以备将来使用。 样本可能是

ROW | COLUMN_A | COLUMN_B | COLUMN_C | SEQ_NUM <= Want this column
1       A           B          1         1
2       A           B          1         2
3       A           B          2         1
4       A           B          2         2
5       A           B          2         3

这些值应该像(COLUMN_A, COLUMB_B, COLUMN_C)一样唯一,但是我不能使用唯一索引,因为我也需要那些重复的值,我只需要跟踪幻影的顺序。所以我添加了一列SEQ_NUM来跟踪这些重复。

我这样填写:

begin
        declare done boolean default false;
        declare _A varchar(1);
        declare _B varchar(1);
        declare _C integer unsigned;
        declare cur cursor for 
            select COLUMN_A , COLUMN_B , COLUMN_C
            from tmp_horario 
            group by COLUMN_A , COLUMN_B , COLUMN_C
            having count(*) > 1; -- Here I loop throught the repeated values
        declare continue handler for not found set done := true;
        open cur;
        loop_dup: loop
            fetch cur into _A, _B, _C;
            if done then
                leave loop_dup;
            end if;
            set @_seq = 0; -- I initialize my sequence in 0 to start
            update tmp_table h
            set h.SEQ_NUM = (@_seq := @_seq + 1) -- Set the next sequential to the repeated values
            where h.COLUMN_A  = _A
                and h.COLUMN_B  = _B
                and h.COLUMN_C = _C;

        end loop loop_dup;

        close cur;
    end;

注意:该表有更多列使光标(获取)更大的痛苦。 正如你所看到的那样,除了我的商店从20秒到80秒,我发现有点令人失望(已经检查过的索引并且它们正在被正确使用)之外,它的工作方式就像魅力一样,我相信问题在于使用光标。

我的问题是:有没有办法在没有光标的情况下在单个查询中设置该着名的序列号?。

2 个答案:

答案 0 :(得分:1)

假设您希望在向表中插入值时发生这种情况,您可以这样做:

INSERT INTO tmp_horario(COLUMN_A, COLUMN_B, COLUMN_C, SEQ_NUM)
VALUE(A_VAL, B_VAL, C_VAL, (IFNULL((
    SELECT MAX(SEQ_NUM)
    FROM tmp_horario AS a
    WHERE a.COLUMN_A = A_VAL AND a.COLUMN_B = B_VAL AND a.COLUMN_C = C_VAL), 0)+1));

基本前提是您查找具有相同值的行,获取最大顺序值(如果存在),然后为新值添加一个。如果未找到匹配项,则将插入值设置为1。如果需要调整此查询,IFNULL语句就是获取SEQ_NUM所需的全部内容。

答案 1 :(得分:1)

是的,非常像你的光标

  DROP TABLE IF EXISTS T;
    CREATE TABLE T(ROW INT, COLUMN_A VARCHAR(1), COLUMN_B VARCHAR(1), COLUMN_C VARCHAR(1), SEQ_NUM INT);
    INSERT INTO T VALUES
    (1  ,     'A' ,          'B'       ,   1,NULL),
    (2  ,     'A' ,          'B'       ,   1,NULL),
    (3  ,     'A' ,          'B'       ,   2,NULL),
    (4  ,     'A' ,          'B'       ,   2,NULL),
    (5  ,     'A' ,          'B'       ,   2,NULL);

UPDATE T 
JOIN (
SELECT T.ROW,
                IF(CONCAT(T.COLUMN_A,T.COLUMN_B,T.COLUMN_C) <> @P , @RN:=1,@RN:=@RN+1) RN,
                @P:=CONCAT(T.COLUMN_A,T.COLUMN_B,T.COLUMN_C) P
            FROM T , (SELECT @RN:=0,@P:=0) R
            ORDER BY ROW

        ) S ON S.ROW = T.ROW
SET SEQ_NUM = S.RN
WHERE 1 = 1

MariaDB [sandbox]> SELECT * FROM T;
+------+----------+----------+----------+---------+
| ROW  | COLUMN_A | COLUMN_B | COLUMN_C | SEQ_NUM |
+------+----------+----------+----------+---------+
|    1 | A        | B        | 1        |       1 |
|    2 | A        | B        | 1        |       2 |
|    3 | A        | B        | 2        |       1 |
|    4 | A        | B        | 2        |       2 |
|    5 | A        | B        | 2        |       3 |
+------+----------+----------+----------+---------+
5 rows in set (0.00 sec)