Как извлечь числовое значение из строки в запросе MySQL? - PullRequest
15 голосов
/ 11 июня 2009

У меня есть таблица с двумя столбцами: price (int) и price_display (varchar).

цена - это действительная числовая цена, например, "9990"

price_display - это визуальное представление, например «$ 9,99» или «9,99Fr»

Мне удалось подтвердить совпадение двух столбцов с помощью регулярного выражения:

цена_отображение не регулярное выражение формат (цена / 1000, 2)

Но в случае несоответствия я хочу извлечь значение из столбца price_display и установить его в столбце цены, все в контексте оператора обновления. Я не смог понять, как.

Спасибо.

Ответы [ 6 ]

33 голосов
/ 14 июня 2009

Эта функция выполняет только возврат цифр 0-9 из строки, что прекрасно решает вашу проблему, независимо от того, какие префиксы или постфиксы у вас есть.

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

Скопировано здесь для справки:

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
5 голосов
/ 11 июня 2009

Один из подходов состоит в использовании REPLACE () function:

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

Это работает для данных примеров, которые вы дали:

'$9.99'
'9.99Fr'

Оба результата дают 999 в моем тесте. При таком обновлении важно сначала выполнить резервное копирование базы данных и знать о форматах элементов. Вы можете увидеть всех "злодеев", выполнив этот запрос:

SELECT   DISTINCT price_display
FROM     my_table
WHERE    price_display not regexp format(price/1000, 2)
ORDER BY price_display;
4 голосов
/ 06 апреля 2015

Для меня CASTING поле сделало свое дело:

CAST( price AS UNSIGNED ) // Для положительного целого числа

CAST( price AS SIGNED ) // Для отрицательного и положительного целого числа

IF(CAST(price AS UNSIGNED)=0,REVERSE(CAST(REVERSE(price) AS UNSIGNED)),CAST(price AS UNSIGNED)) // Исправлено, когда цена начинается с чего-то другого, чем цифра

Подробнее см .:

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

1 голос
/ 23 октября 2016

Возвращает последний номер из строки:

CREATE FUNCTION getLastNumber(str VARCHAR(255)) RETURNS INT(11)
DELIMETER //
BEGIN
    DECLARE last_number, str_length, position INT(11) DEFAULT 0;
    DECLARE temp_char VARCHAR(1);
    DECLARE temp_char_before VARCHAR(1);


IF str IS NULL THEN
    RETURN -1;
END IF;

SET str_length = LENGTH(str);

WHILE position <= str_length DO
    SET temp_char = MID(str, position, 1);

    IF position > 0 THEN
        SET temp_char_before = MID(str, position - 1, 1);
    END IF;

    IF temp_char BETWEEN '0' AND '9' THEN
        SET last_number = last_number * 10 + temp_char;
    END IF;
    IF (temp_char_before NOT BETWEEN '0' AND '9') AND 
           (temp_char BETWEEN '0' AND '9') THEN                 
        SET last_number = temp_char;
    END IF;

    SET position = position + 1;
END WHILE;

RETURN last_number;
END//
DELIMETER;

Затем вызовите эту функцию:

select getLastNumber ("ssss111www222w"); печать 222

выберите getLastNumber ("ssss111www222www3332"); печать 3332

1 голос
/ 20 августа 2013

Я создаю процедуру, которая обнаруживает первое число в строке и возвращает его, если не возвращает 0.

    DROP FUNCTION IF EXISTS extractNumber;
    DELIMITER //
    CREATE FUNCTION extractNumber (string1 VARCHAR(255)) RETURNS INT(11) 
        BEGIN
        DECLARE position, result, longitude INT(11) DEFAULT 0;
        DECLARE string2 VARCHAR(255);
        SET longitude = LENGTH(string1);
        SET result = CONVERT(string1, SIGNED);
        IF result = 0 THEN
            IF string1 REGEXP('[0-9]') THEN
                SET position = 2;
                checkString:WHILE position <= longitude DO
                    SET string2 = SUBSTR(string1 FROM position);
                    IF CONVERT(string2, SIGNED) != 0 THEN
                        SET result = CONVERT(string2, SIGNED);
                        LEAVE checkString;
                    END IF;
                    SET position = position + 1;
                END WHILE;
           END IF;
        END IF;
        RETURN result;
    END //
    DELIMITER ;
0 голосов
/ 11 июня 2009

Это «ужас кодирования», схемы реляционных баз данных должны НЕ записываться так!

Вы должны написать сложный и ненужный код для проверки данных.

Попробуйте что-то вроде этого:

SELECT CONCAT('$',(price/1000)) AS Price FROM ...

Кроме того, вы можете использовать float, double или real вместо целого числа.

Если вам нужно сохранить данные о валюте, вы можете подумать о добавлении поля валюты или использовать системные языковые функции для отображения в правильном формате.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...