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

北城余情 提交于 2019-12-01 05:31:46

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

Well...

Select position('#' in '2010-####-3434');

will give you the first. If you want the last, just run that again with the reverse of your string. A pl/pgsql string reverse can be found here.

Select length('2010-####-3434') - position('#' in reverse_string('2010-####-3434')) + 1;
Autumn Gao

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,''));  
$$;

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;

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.

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');
Tomasz Kozik

My example:

reverse(substr(reverse(newvalue),0,strpos(reverse(newvalue),',')))
  1. Reverse all string
  2. Substring string
  3. Reverse result
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!