How to select the part of a column between _ and a - postgresql

i have a column href which contiens a liste of links
href
100712107%23C3.3_.pdf
100712107~%23C3.2_C00.zip
100740104_C2.3.xls
testme_aze_--b00.xls
My ouput would be
href
name
rev
100712107%23C3.3_.pdf
100712107%23C3.3
100712107~%23C3.2_C00.zip
100712107~%23C3.2
C00
100740104_C2.3.xls
100740104
C2.3
testme_aze_--b00.xls
testme_aze
--b00
I have tried to use ** reverse(split_part(reverse(href),'.',1))**

You can use a regex together with substring() to extract the parts you want:
select href,
substring(href from '(.*)_') as name,
substring(href from '.*_(.*)\.') as rev
from the_table
returns:
href | name | rev
--------------------------+-------------------+------
100712107%23C3.3_.pdf | 100712107%23C3.3 |
100712107~%23C3.2_C00.zip | 100712107~%23C3.2 | C00
100740104_C2.3.xls | 100740104 | C2.3
testme_aze_--b00.xls | testme_aze | --b00
substring() will return the first group from the regex. The firs regex matches all characters until the last _.
The second expression matches everything after the last _ up until the last .

You want add a column to the table ?
ALTER TABLE TABLE_NAME ADD COLUMN HREF VARCHAR(255) NOT NULL;

Related

How to update JSONB column with value coming from another table column in PostgreSQL

I have a source table, which lists like below:
public.source
Id | part_no | category
1 | 01270-4 | Landscape
2 | 01102-3 | Sports
Then, I have target table with jsonb column (combinations) , which list like below;
public.target
Id | part_no | combinations
7 | 01270-4 | {"subject":""}
8 | 01102-3 | {"subject":""}
My problem is - how I can update the target table with jsonb column (combinations) with the values coming from source table using the part_no column?
Output like:
Id | part_no | combinations
7 | 01270-4 | {"subject":"Landscape"}
8 | 01102-3 | {"subject":"Sports"}
I tried below but giving error:
UPDATE public.target t
SET combinations = jsonb_set(combinations,'{subject}','s.category',false)
FROM public.source s
WHERE s.part_no = t.part_no;
ERROR: invalid input syntax for type json
LINE 2: SET combinations = jsonb_set(combinations,'{subject}', 's.categor...
^
DETAIL: Token "s" is invalid.
CONTEXT: JSON data, line 1: s...
SQL state: 22P02
Character: 77
You should use to_jsonb function to convert s.category to JSON
Demo
UPDATE public.target t
SET combinations = jsonb_set(combinations,'{subject}',to_jsonb(s.category),false)
FROM public.source s
WHERE s.part_no = t.part_no
Or you can use sample structure for join and update two JSON field:
Demo
UPDATE public.target t
SET combinations = combinations || jsonb_build_object('subject', s.category)
FROM public.source s
WHERE s.part_no = t.part_no

How to use dynamic table name for sub query where the dynamic value coming from its own main query in PostgreSQL?

I have formed this query to get the desired output mentioned below:
select tbl.id, tbl.label, tbl.input_type, tbl.table_name
case when tbl.input_type = 'dropdown' or tbl.input_type = 'searchable-dropdown'
then (select json_agg(opt) from tbl.table_name) as opt) end as options
from mst_config as tbl;
I want output like below:
id | label | input_type | table_name | options
----+----------------------------------------------------+---------------------+-------------------------+-----------------------------------------------------------
1 | Gender | dropdown | mst_gender | [{"id":1,"label":"MALE"},
| | | | {"id":2,"label":"FEMALE"}]
2 | SS | dropdown | mst_ss | [{"id":1,"label":"something"},
| | | | {"id":2,"label_en":"something"}]
But, I'm facing a problem while using,
select json_agg(opt) from tbl.table_name) as opt
In the above part "tbl.table_name", I wanted to use it as dynamic table name but it's not working.
Then, I have searched a lot and found something like Execute format('select * from %s', table_name), where tablename is the dynamic table name. I have even tried the same with postgres function.
But I faced an issue again while using the format method. The reason is I want to use the variable for which the value needs to come from its own main query value instead of already having it in a variable. so this one was also not working.
I would really appreciate if anyone can help me out on this. Also if there are any other possibilities available to achieve this output, help me on that as well.

Unable to replace dash with null during COPY operation from CSV

I have the following CSV data
"AG","Saint Philip","AG-08"
"AI","Anguilla","-"
"AL","Berat","AL-01"
I want to replace - with NULL
I use the following command
copy subdivision from '/tmp/IP2LOCATION-ISO3166-2.CSV' with delimiter as ',' NULL AS '-' csv;
The copy operation is success. However, - in 3rd column is being copied as well, instead of replaced with NULL.
Do you have idea what mistake in my command? My table is
CREATE TABLE subdivision(
country_code TEXT NOT NULL,
name TEXT NOT NULL,
code TEXT
);
It comes down to the quoting. If you have this:
"AI","Anguilla",-
"AL","Berat","AL-01"
Then the below works(using newer COPY format):
copy
subdivision
from
'/home/postgres/csv_test.csv'
with(format csv, delimiter ',' , NULL '-');
COPY 3
\pset null NULL
select * from subdivision ;
country_code | name | code
--------------+--------------+-------
AG | Saint Philip | AG-08
AI | Anguilla | NULL
AL | Berat | AL-01
If you maintain the original csv:
"AG","Saint Philip","AG-08"
"AI","Anguilla","-"
"AL","Berat","AL-01"
then you have to do this:
copy
subdivision
from
'/home/postgres/csv_test.csv'
with(format csv, delimiter ',' , NULL '-', FORCE_NULL (code) );
select * from subdivision ;
country_code | name | code
--------------+--------------+-------
AG | Saint Philip | AG-08
AI | Anguilla | NULL
AL | Berat | AL-01
where FORCE_NULL is:
https://www.postgresql.org/docs/current/sql-copy.html
FORCE_NULL
Match the specified columns' values against the null string, even if it has been quoted, and if a match is found set the value to NULL. In the default case where the null string is empty, this converts a quoted empty string into NULL. This option is allowed only in COPY FROM, and only when using CSV format.
So to convert quoted values you have to force the conversion by specifying the columns(s)

problems with full-text search in postgres

I have the next table, and data:
/* script for people table, with field tsvector and gin */
CREATE TABLE public.people (
id INTEGER,
name VARCHAR(30),
lastname VARCHAR(30),
complete TSVECTOR
)
WITH (oids = false);
CREATE INDEX idx_complete ON public.people
USING gin (complete);
/* data for people table */
INSERT INTO public.people ("id", "name", "lastname", "complete")
VALUES
(1, 'MICHAEL', 'BRYANT BRYANT', '''bryant'':2,3 ''michael'':1'),
(2, 'HENRY STEVEN', 'BUSH TIESSEN', '''bush'':3 ''henri'':1 ''steven'':2 ''tiessen'':4'),
(3, 'WILLINGTON STEVEN', 'STEPHENS FLINN', '''flinn'':4 ''stephen'':3 ''steven'':2 ''willington'':1'),
(4, 'BRET', 'MARTINEZ AROCH', '''aroch'':3 ''bret'':1 ''martinez'':2'),
(5, 'TERENCE BERT', 'CAVALIERE ENRON', '''bert'':2 ''cavalier'':3 ''terenc'':1');
I need retrieve the names and lastnames, according the tsvector field. Actually I have the query:
SELECT * FROM people WHERE complete ## to_tsquery('WILLINGTON & FLINN');
And the result is right (the third record). BUT if I try with
SELECT * FROM people WHERE complete ## to_tsquery('STEVEN & FLINN');
/* the same record! */
I don't have results. Why? What can I do?
You should use the same language to search your table as the values in your field 'complete' where inserted.
Check the result of that query compared english and german:
select * ,
to_tsvector('english', concat_ws(' ', name, lastname )) as english,
to_tsvector('german', concat_ws(' ', name, lastname )) as german
from public.people
so that should work for you :
SELECT * FROM people WHERE complete ## to_tsquery('english','STEVEN & FLINN');
You are probably using a text search configuration where either STEVEN or FLINN are modified by stemming.
I can reproduce this here:
test=> SHOW default_text_search_config;
default_text_search_config
----------------------------
pg_catalog.german
(1 row)
test=> SELECT complete FROM public.people WHERE id = 3;
complete
-------------------------------------------------
'flinn':4 'stephen':3 'steven':2 'willington':1
(1 row)
test=> SELECT * FROM ts_debug('STEVEN & FLINN');
alias | description | token | dictionaries | dictionary | lexemes
-----------+-----------------+--------+---------------+-------------+---------
asciiword | Word, all ASCII | STEVEN | {german_stem} | german_stem | {stev}
blank | Space symbols | | {} | |
blank | Space symbols | & | {} | |
asciiword | Word, all ASCII | FLINN | {german_stem} | german_stem | {flinn}
(4 rows)
test=> SELECT * FROM public.people
WHERE complete ## to_tsquery('STEVEN & FLINN');
id | name | lastname | complete
----+------+----------+----------
(0 rows)
So you see, the German Snowball dictionary stems STEVEN to stev.
Since complete contains the unstemmed version steven, no match is found.
You should use the same text search configuration when you populate complete and in the query.

get all rows preceded and followed by whitespace

for example i have the following table (let's call it, comodity)
+-----------+
|name |
+-----------+
|kemasan |
|fe emas ex |
+-----------+
using the following query
SELECT * FROM comodity WHERE name ILIKE '%emas%'
give me two rows kemasan and fe emas ex, however I want to select only the second row fe emas ex. how to do that?
PS: it's also SHOULD NOT preceded/followed by any visible character.
Thanks in advance
SELECT *
FROM (VALUES
('blah emas blah'),
('vlademask'),
('emas1'),
('1emas'),
('emas'),
('1 emas'),
('emas 1')
) as commodity(word)
WHERE word ~* '\yemas\y'
Use a regular expression that matches words or start and stop markers.