Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to recalculate a field on GROUP

I have a table like

f1|f2|fk
1 | 0|100
1 | 1|200
1 | 2|300
1 | 3|400
2 | 0|300
2 | 1|400
2 | 2|500

Where (f1,f2) is the PK and fk is a foreign key. There are not many values for fk, about 20. f2 is never more than 3. There are a lot of (f1,f2) pairs, however. (f1,fk) is UNIQUE.

Now, say we are mapping 100 and 200 to A, 300 and 400 to B, 500 to C -- this mapping is a given. We would like (f1_new,fk_mapped) to stay UNIQUE. This is so far solved roughly by

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

Now, the problem is that we need to keep f2 values 0, 1, 2 in the mapped table, so this is the desired result:

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

I really would like to keep this within MySQL.

like image 416
chx Avatar asked Oct 22 '22 02:10

chx


1 Answers

I think this should do it:

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

FIDDLE

like image 118
Barmar Avatar answered Oct 24 '22 09:10

Barmar