PostgreSQL: в ОДНОМ SQL-синтаксисе по числовому значению, вычисленному из текстового столбца - PullRequest
2 голосов
/ 01 октября 2011

Столбец имеет строковые значения, такие как «1/200», «3.5» или «6». Как я могу преобразовать эту строку в числовое значение в одном запросе SQL?

Мой фактический SQL более сложный, вот простой пример:

SELECT number_value_in_string FROM table 

Формат number_value_in_string будет одним из:

  • ##
  • #. ##
  • # / ###

Мне нужно отсортировать по числовому значению этого столбца. Но, конечно, postgres не согласен со мной, что 1/200 - это правильное число.

Ответы [ 4 ]

1 голос
/ 01 октября 2011

Видя ваше имя, я не могу не опубликовать упрощение вашего ответа:

SELECT id, number_value_in_string FROM table
 ORDER BY CASE WHEN substr(number_value_in_string,1,2) = '1/'
        THEN 1/substr(number_value_in_string,3)::numeric 
        ELSE number_value_in_string::numeric END, id;

Игнорирование возможного деления на ноль.

1 голос
/ 01 октября 2011

Этот postgres SQL делает свое дело:

select (parts[1] :: decimal) / (parts[2] :: decimal) as quotient
FROM (select regexp_split_to_array(number_value_in_string, '/') as parts from table) x

Вот тест этого кода:

select (parts[1] :: decimal) / (parts[2] :: decimal) as quotient
FROM (select regexp_split_to_array('1/200', '/') as parts) x

Вывод:

0.005

Обратите внимание, что вы бынеобходимо обернуть это в оператор case для защиты от ошибок деления на ноль и / или ошибок массива вне границ и т. д., если столбец не содержит косую черту

Примечаниетакже, что вы можете сделать это без внутреннего выбора, но вам придется использовать regexp_split_to_array дважды (один раз для каждой части), и вы, вероятно, понесете удар по производительности.Тем не менее, может быть проще встроить код и просто принять небольшую потерю производительности.

1 голос
/ 01 октября 2011

Мне удалось решить мою проблему.Спасибо всем.Это происходит примерно так в одном SQL.(Я использую POSTGRESQL)

Это будет сортировать строку, приходящую как "#", "#. #" Или "1 / #"

SELECT id, number_value_in_string FROM table ORDER BY CASE WHEN position('1/' in number_value_in_string) = 1 
    THEN 1/substring(number_value_in_string from (position('1/' in number_value_in_string) + 2) )::numeric 
    ELSE number_value_in_string::numeric 
END ASC, id

Надеюсь, это поможеткто-то в будущем.

1 голос
/ 01 октября 2011

Я бы определил хранимую функцию для преобразования строки в числовое значение, примерно так:

CREATE OR REPLACE FUNCTION fraction_to_number(s CHARACTER VARYING)
RETURN DOUBLE PRECISION AS
BEGIN
   RETURN
   CASE WHEN s LIKE '%/%' THEN
       CAST(split_part(s, '/', 1) AS double_precision) 
       / CAST(split_part(s, '/', 2) AS double_precision)
   ELSE
       CAST(s AS DOUBLE PRECISION)
   END CASE
END

Тогда вы можете ORDER BY fraction_to_number(weird_column)

Если возможно, я бы вновь посетил проект данных. Неужели вся эта сложность действительно необходима?

...