MySql - 根据另一列增加

时间:2014-05-28 14:17:10

标签: mysql

我有一个包含3列的表(innoDB):ID,ID_FATHER,ROWPOS。 ID为auto_increment,ROWPOS具有其他表中的值。如果ROWPOS不是序列,我需要ID_FATHER增加1,如果它是序列ID_FATHER不应该递增。

像这样:

ID | ID_FATHER | ROWPOS

1  |    1      | 250            
2  |    2      | 253
3  |    2      | 254
4  |    3      | 260
5  |    4      | 263
6  |    5      | 268
7  |    6      | 270
8  |    6      | 271
9  |    6      | 272
10 |    7      | 276

有办法吗?

使用此查询:

INSERT INTO mytable (i, rowpos)
SELECT @i := IF(t.rowpos = @prev_rowpos + 1, @i, @i + 1) AS i
     , @prev_rowpos := t.rowpos AS rowpos
  FROM temp
  JOIN (SELECT @prev_rowpos := NULL, @i := 0) v
 ORDER BY t.rowpos

我可以导入到我想要的表格中。但问题出在TABLE.Service中,正如您在此解决方案中看到的那样,ID_FATHER是错误的,因为它只增加1 但在这种情况下它实际上应该是2,因为发票1没有服务。

如何在不更改所有架构的情况下解决此问题。

TABLE.temp

ROW|TYPE |INVOICE_temp 
 1 |xxx  |10
 2 |xxP  |led tv
 3 |xxP  |mp3 Player
 4 |xxx  |11
 5 |xxP  |tv cable
 6 |xxS  |install

xxx = Invoice number
xxP = Product
xxs = service

TABLE.Invoice_Number             TABLE.Product                 

ID|ID_FATHER|ROWPOS|NUM    ID|ID_FATHER|ROWPOS|PROD        
1 |    1    | 1    | 10    1 |   1     |  2   | led tv                  
2 |    2    | 4    | 11    2 |   1     |  3   | mp3 player  
                           3 |   2     |  5   | tv cable

TABLE.Service

ID|ID_FATHER|ROWPOS|SERV
1 |    1    |   6  | install 

我在查询中做了一些更改,以便按需要工作。

2 个答案:

答案 0 :(得分:0)

E.g:

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,rowpos INT NOT NULL
);

INSERT INTO my_table (rowpos) VALUES
(250),
(253),
(254),
(260),
(263),
(268),
(270),
(271),
(272),
(276);


SELECT x.*
     , @i:=@i+ISNULL(y.id) i 
  FROM my_table x 
  LEFT 
  JOIN my_table y 
    ON y.id < x.id 
   AND y.rowpos = x.rowpos - 1
     , (SELECT @i:=0) vals 
 ORDER  
    BY x.id;
+----+--------+------+
| id | rowpos | i    |
+----+--------+------+
|  1 |    250 |    1 |
|  2 |    253 |    2 |
|  3 |    254 |    2 |
|  4 |    260 |    3 |
|  5 |    263 |    4 |
|  6 |    268 |    5 |
|  7 |    270 |    6 |
|  8 |    271 |    6 |
|  9 |    272 |    6 |
| 10 |    276 |    7 |
+----+--------+------+

答案 1 :(得分:0)

你可以这样做:

INSERT INTO mytable (i, rowpos)
SELECT @i := IF(t.rowpos = @prev_rowpos + 1, @i, @i + 1) AS i
     , @prev_rowpos := t.rowpos AS rowpos
  FROM another_table t
  JOIN (SELECT @prev_rowpos := NULL, @i := 0) v
 ORDER BY t.rowpos

(只测试SELECT查询,在用INSERT作为前缀之前,返回你想要的结果集。)


为了完整起见,我将补充说,这种技术依赖于MysQL中的UNDOCUMENTED和非保证行为,使用“用户变量”。我已成功多次使用此方法,但对于“一次性”类型的管理功能,并未在应用程序中作为SQL嵌入。

请注意,SELECT列表中表达式的ORDER很重要,它们按照它们在SELECT列表中出现的顺序进行计算。 (MySQL不保证这种行为,但我们确实观察到它。重要的是检查包含前一行到的值的用户变量将当前行值分配给用户变量这就是首先返回i,然后是rowpos的原因。如果你颠倒了SELECT列表中那些的顺序,查询将以不同的方式运行,我们将得不到相同的结果。

内联视图(别名为v)的目的是初始化用户变量。由于MySQL在外部查询运行之前将该查询查询实现为“派生表”,因此这些变量在外部查询中被引用之前会被初始化。我们并不关心内联视图查询实际返回什么,除了我们需要它只返回一行(因为我们在JOIN操作中将它引用到我们真正想要查询的表)。