PostgreSQL: IN A SINGLE SQL SYNTAX order by numeric value computed from a text column

女生的网名这么多〃 提交于 2019-12-20 02:59:28

问题


A column has a string values like "1/200", "3.5" or "6". How can I convert this String to numeric value in single SQL query?

My actual SQL is more complicated, here is a simple example:

SELECT number_value_in_string FROM table 

number_value_in_string's format will be one of:

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

I need to sort by the numeric value of this column. But of course postgres doesn't agree with me that 1/200 is a proper number.


回答1:


Seeing your name I cannot but post a simplification of your answer:

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;

Ignoring possible divide by zero.




回答2:


I would define a stored function to convert the string to a numeric value, more or less like this:

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

Then you can ORDER BY fraction_to_number(weird_column)

If possible, I would revisit the data design. Is it all this complexity really necessary?




回答3:


This postgres SQL does the trick:

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

Here's a test of this code:

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

Output:

0.005

Note that you would need to wrap this in a case statement to protect against divide-by-zero errors and/or array out of bounds issues etc if the column did not contain a forward slash

Note also that you could do it without the inner select, but you would have to use regexp_split_to_array twice (once for each part) and you would probably incur a performance hit. Nevertheless, it may be easier to code in-line and just accept the small performance loss.




回答4:


I managed to solve my problem. Thanks all. It goes something like this, in a single SQL. (I'm using POSTGRESQL)

It will sort a string coming in as either "#", "#.#" or "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

Hope this will help someone outhere in the future.



来源:https://stackoverflow.com/questions/7617110/postgresql-in-a-single-sql-syntax-order-by-numeric-value-computed-from-a-text-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!