Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何重新计算组上的字段_Mysql_Sql_Select_Insert - Fatal编程技术网

Mysql 如何重新计算组上的字段

Mysql 如何重新计算组上的字段,mysql,sql,select,insert,Mysql,Sql,Select,Insert,我有一张像这样的桌子 f1|f2|fk 1 | 0|100 1 | 1|200 1 | 2|300 1 | 3|400 2 | 0|300 2 | 1|400 2 | 2|500 其中(f1,f2)是主键,fk是外键。fk的值不多,大约为20。f2永远不超过3。然而,有很多(f1,f2)对(f1,fk)是唯一的 现在,假设我们将100和200映射到A,300和400到B,500到C,这个映射是给定的。我们希望(f1\u新,fk\u映射)保持唯一性。到目前为止,这一问题已大致解决 INSERT

我有一张像这样的桌子

f1|f2|fk
1 | 0|100
1 | 1|200
1 | 2|300
1 | 3|400
2 | 0|300
2 | 1|400
2 | 2|500
其中
(f1,f2)
是主键,fk是外键。fk的值不多,大约为20。f2永远不超过3。然而,有很多
(f1,f2)
对<代码>(f1,fk)是唯一的

现在,假设我们将100和200映射到A,300和400到B,500到C,这个映射是给定的。我们希望
(f1\u新,fk\u映射)
保持
唯一性
。到目前为止,这一问题已大致解决

INSERT INTO mapped (f1_new,f2_new,fk_new)
SELECT f1, MIN(f2), CASE fk WHEN 100 THEN A WHEN 200 THEN A END AS fk
FROM origin
GROUP BY f1, fk
现在,问题是我们需要在映射表中保留f2值0、1、2,因此这是期望的结果:

f1_new|f2_new|fk_mapped
1     | 0    |A
1     | 1    |B
2     | 0    |B
2     | 1    |C

我真的很想把它保存在MySQL中。

我认为这应该可以做到:

INSERT INTO mapped (f1_new, f2_new, fk_new)
SELECT f1_new, f2_new, fk_new from (
    SELECT f1_new, @f2 := if(f1_new = @prev_f1, @f2+1, 0) f2_new, fk_new, @prev_f1 := f1_new
    FROM (select f1 AS f1_new, CASE WHEN fk IN (100, 200) THEN 'A'
                                    WHEN fk in (300, 400) THEN 'B'
                                    WHEN fk = 500 THEN 'C'
                               END AS fk_new
          FROM origin
          GROUP BY f1_new, fk_new
          ORDER BY f1_new, fk_new) new,
         (SELECT @f2 := NULL, @prev_f1 := NULL) vars
    ) x

我很困惑-您说您希望在映射表中保留所有
f2
的三个值,但是您显示的所需结果没有
f2==2
的实例?他希望分配
f2
的新值,因此它们保留在0、1、2。。。为
f1
的特定值排序。这是一个per-f1排名列。啊。知道了。我猜第一个示例表中的第四行应该是
f2==3
。特别是如果
(f1,f2)
是主键。我修复了第一个表,它实际上是一个3。用f1=entity\u id,f2=delta,f3=target\u id重写它真的更有帮助吗?我可以,但我不确定这有多大帮助。我相信上面的内容很好,但“不可预测”。你不知道@prev_f1:=是否先开火。但是
@f2:=if(f1_new=@prev_f1,@f2+1,0)+最少(0,@prev_f1:=f1_new)
应该可以工作,因为
+
是从左到右的。同样,per的想法:如果使用GROUP BY,输出行将按照GROUP BY列进行排序,就像对相同的列有ORDER BY一样。@chx我已经多次看到并使用过这种变体。虽然它可能无法保证,但实际上我认为它总是从左到右起作用。