How to find the first and last occurrences of a specific character inside a string in PostgreSQL

前端 未结 7 1159
闹比i
闹比i 2021-01-11 20:26

I want to find the first and the last occurrences of a specific character inside a string. As an example, consider a string named \"2010-####-3434\", and suppose the charact

相关标签:
7条回答
  • 2021-01-11 20:41

    Another way to count last position is to slit string to array by delimeter equals to needed character and then substract length of characters for the last element from the length of whole string

    CREATE FUNCTION last_pos(char, text) RETURNS INTEGER AS
    $$
    select length($2) - length(a.arr[array_length(a.arr,1)]) 
    from (select string_to_array($2, $1) as arr) as a
    $$ LANGUAGE SQL;
    

    For the first position it is easier to use

    select position('#' in '2010-####-3434');
    
    0 讨论(0)
  • 2021-01-11 20:42

    I do not know how to do that, but the regular expression functions like regexp_matches, regexp_replace, and regexp_split_to_array may be an alternative route to solving your problem.

    0 讨论(0)
  • 2021-01-11 20:42

    In the case where char = '.', an escape is needed. So the function can be written:

    CREATE OR REPLACE FUNCTION last_post(text,char) 
    RETURNS integer LANGUAGE SQL AS $$  
    select length($1)- length(regexp_replace($1, E'.*\\' || $2,''));  
    $$;
    
    0 讨论(0)
  • 2021-01-11 20:43

    My example:

    reverse(substr(reverse(newvalue),0,strpos(reverse(newvalue),',')))
    
    1. Reverse all string
    2. Substring string
    3. Reverse result
    0 讨论(0)
  • 2021-01-11 20:49

    This pure SQL function will provide the last position of a char inside the string, counting from 1. It returns 0 if not found ... But (big disclaimer) it breaks if the character is some regex metacharacter ( .$^()[]*+ )

    CREATE FUNCTION last_post(text,char) RETURNS integer AS $$ 
         select length($1)- length(regexp_replace($1, '.*' || $2,''));
    $$ LANGUAGE SQL IMMUTABLE;
    
    test=# select last_post('hi#-#-#byte','#');
     last_post
    -----------
             7
    
    test=# select last_post('hi#-#-#byte','a');
     last_post
    -----------
             0
    

    A more robust solution would involve pl/pgSQL, as rfusca's answer.

    0 讨论(0)
  • 2021-01-11 20:52

    9.5+ with array_positions

    Using basic PostgreSQL array functions we call string_to_array(), and then feed that to array_positions() like this array_positions(string_to_array(str,null), c)

    SELECT
      arrpos[array_lower(arrpos,1)] AS first,
      arrpos[array_upper(arrpos,1)] AS last
    FROM ( VALUES
      ('2010-####-3434', '#')
    ) AS t(str,c)
    CROSS JOIN LATERAL array_positions(string_to_array(str,null), c)
      AS arrpos;
    
    0 讨论(0)
提交回复
热议问题