PostgreSQL: how can I shorten a multi-word string to few words?

Turn the sentence into an array, then pick the first three elements and concatenate them back to a single string:

select array_to_string ((regexp_split_to_array(title, '\s+'))[1:3], ' ')
from book;

alternatively, just use split_part() three times:

select split_part(title, ' ', 1)||
       split_part(title, ' ', 2)||  
       split_part(title, ' ', 3)
from book;

split_part() has the disadvantage, that you can't properly deal with multiple spaces between the words.


Use a regular expression, like so:

select substring('hello everyone out there somewhere', '[^ ]+[ ]+[^ ]+[ ]+[^ ]+');

Slightly bigger example, which includes examples of handling apostrophes in string literals (the sentences have been taken from another question):

create table sentences ( s varchar(128) ) ;

insert into sentences values 
('How to left join and count two tables where the rows (strings) are different'),
('I have two tables - t1, t2.'),
('t1 has a title column with titles separated by spaces.'),
('t2 has a path column with paths separated by dashes and prefixed ''path/'''),
('GOAL: FOR EACH t1.title COUNT THE NUMBER OF TIMES IT SHOWS UP IN t2'),
('Course of action: parse t2.path so that it looks like t1.title in order to do a left join and count'),
('I''m very new to this, if you have a better approach altogether I would appreciate any suggestions'),
('So far I have:'),
('select t1.title, count(t2.path) as num '),
('from t1 left join t2 on t1.title = substring(log.path from 6) '),
('where t1.title like ''%''||split_part(substring(log.path from 6),''-'',1)||''%'' 
'),
('group by articles.title; ');

-- pick the first 3 words
select substring(s, '[^ ]+[ ]+[^ ]+[ ]+[^ ]+')
from sentences;

            substring            
---------------------------------
 How to left
 I have two
 t1 has a
 t2 has a
 GOAL: FOR EACH
 Course of action:
 I'm very new
 So far I
 select t1.title, count(t2.path)
 from t1 left
 where t1.title like
 group by articles.title;
(12 rows)