简体   繁体   中英

Using SQL (for MySQL), how can I UPDATE data on a row based on data from a previous row?

I have these product SKUs in column scott that are alphanumeric (should always contain a number but not always a letter). The id column is auto-incremented. All of the data was imported line-by-line from a CSV file, so I know the order of the data is correct.

As you can see from this picture, some scott fields are just letters, which should have the previous number in front of them. For example, on id 5149, I'd like the scott to be 3780a.

在此输入图像描述

So the question is this: Using SQL, how can I parse through the rows in order, prepending the scott number from the most recent field that contained a number, onto fields following it that don't contain a number?

Here's one option using a user-defined variable to determine the most recent previous numeric value.

update yourtable y
join (
  select id, scott, @prevNumericId:=
          if(scott REGEXP '^[0-9]+$', scott, @prevNumericId) prevNumericId
  from yourtable, (select @prevNumericId:=0) t
  order by id   
  ) t on y.id = t.id and y.scott = t.scott
set y.scott = concat(t.prevNumericId,y.scott)
where y.scott not REGEXP '^[0-9]+$'
update t
set scott = CONCAT(
           (select scott
            from tablename
            where id = t.id - 1),
            scott)
from tablename t
where Scott not like '%0%'
and Scott not like '%1%'
and Scott not like '%2%'
and Scott not like '%3%'
and Scott not like '%4%'
and Scott not like '%5%'
and Scott not like '%6%'
and Scott not like '%7%'
and Scott not like '%8%'
and Scott not like '%9%'

That good old first-(or in this case, last)-child problem, but this time on the same table..

This should do the job quite elegantly for you:

UPDATE mytable dest
JOIN (
SELECT mt.id, CONCAT(lnk.scott, mt.scott) AS newValue
FROM mytable mt

LEFT OUTER JOIN mytable lnk ON lnk.id < mt.id AND CONCAT('',SUBSTRING(lnk.scott, 1, 1) * 1) != 0
LEFT OUTER JOIN mytable lnk2 ON lnk2.id < mt.id AND CONCAT('',SUBSTRING(lnk2.scott, 1, 1) * 1) != 0
    AND lnk.id < lnk2.id

WHERE lnk2.id IS NULL
AND CONCAT('',SUBSTRING(mt.scott, 1, 1) * 1) = 0
) AS source on source.id = dest.id

SET dest.scott = source.newValue

===

I don't have enough rep to comment but @sgeddes's solution is basically the same but using the user defined variable. That should be fine so long as the variable doesn't cross over between concurrent executions :)

This version will happily run concurrently, regardless.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM