Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you extract a numerical value from a string in a MySQL query?

I have a table with two columns: price (int) and price_display (varchar).

price is the actual numerical price, e.g. "9990"

price_display is the visual representation, e.g. "$9.99" or "9.99Fr"

I've been able to confirm the two columns match via regexp:

price_display not regexp format(price/1000, 2)

But in the case of a mismatch, I want to extract the value from the price_display column and set it into the price column, all within the context of an update statement. I've not been able to figure out how.

Thanks.

like image 342
Teflon Ted Avatar asked Jun 10 '09 21:06

Teflon Ted


People also ask

How do I separate numbers and text in MySQL?

To split a string in MySQL, you need to make use of the SUBSTRING_INDEX function that is provided by MySQL. The SUBSTRING_INDEX() function allows you to extract a part of a complete string. The syntax of the function is as follows: SUBSTRING_INDEX(expression, delimiter, count);

How do I get only the numeric values of a column in SQL?

In SQL Server, we can use the ISNUMERIC() function to return numeric values from a column. We can alternatively run a separate query to return all values that contain numeric data.


3 Answers

This function does the job of only returning the digits 0-9 from the string, which does the job nicely to solve your issue, regardless of what prefixes or postfixes you have.

http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#815

Copied here for reference:

SET GLOBAL log_bin_trust_function_creators=1;
DROP FUNCTION IF EXISTS digits;
DELIMITER |
CREATE FUNCTION digits( str CHAR(32) ) RETURNS CHAR(32)
BEGIN
  DECLARE i, len SMALLINT DEFAULT 1;
  DECLARE ret CHAR(32) DEFAULT '';
  DECLARE c CHAR(1);

  IF str IS NULL
  THEN 
    RETURN "";
  END IF;

  SET len = CHAR_LENGTH( str );
  REPEAT
    BEGIN
      SET c = MID( str, i, 1 );
      IF c BETWEEN '0' AND '9' THEN 
        SET ret=CONCAT(ret,c);
      END IF;
      SET i = i + 1;
    END;
  UNTIL i > len END REPEAT;
  RETURN ret;
END |
DELIMITER ;

SELECT digits('$10.00Fr'); 
#returns 1000
like image 53
Vladiat0r Avatar answered Nov 15 '22 22:11

Vladiat0r


One approach would be to use REPLACE() function:

UPDATE my_table
SET    price = replace(replace(replace(price_display,'Fr',''),'$',''),'.','')
WHERE  price_display not regexp format(price/1000, 2);

This works for the examples data you gave:

'$9.99'
'9.99Fr'

Both result in 999 in my test. With an update like this, it's important to be sure to back up the database first, and be cognizant of the formats of the items. You can see all the "baddies" by doing this query:

SELECT   DISTINCT price_display
FROM     my_table
WHERE    price_display not regexp format(price/1000, 2)
ORDER BY price_display;
like image 38
artlung Avatar answered Nov 15 '22 21:11

artlung


For me CASTING the field did the trick:

CAST( price AS UNSIGNED ) // For positive integer

CAST( price AS SIGNED ) // For negative and positive integer

IF(CAST(price AS UNSIGNED)=0,REVERSE(CAST(REVERSE(price) AS UNSIGNED)),CAST(price AS UNSIGNED)) // Fix when price starts with something else then a digit

For more details see:

https://dev.mysql.com/doc/refman/5.0/en/cast-functions.html

like image 30
Elwin Avatar answered Nov 15 '22 22:11

Elwin