Pattern matching with identical wildcards - postgresql

I'm working with PostgreSQL and want to know whether you can have a wildcard retain its value.
So for example say I had
select * from tableOne where field like ‘_DEF_’;
Is there a way to get the first and last wildcard to be the exact same character?
So an example matching result could be: ADEFA or ZDEFZ.

You can use a regular expression with a back-reference:
select *
from some_table
where some_column ~* '^(.)DEF(\1)$'
^(.)DEF(\1)$ means: some character at the beginning followed DEF followed by the first character must occur at the end of the string.
The () defines a group and the \1 references the first group (which is the first character in the input sequence in this example)
SQLFiddle example: http://sqlfiddle.com/#!15/d4c4d/1

Use regular expression:
with test as (
select 'xABa' as foo
union select 'xABx'
union select 'xJBx'
)
select * from test
where foo ~* E'^(.)AB\\1$'
Outputs:
foo
------
xABx
(1 row)

Related

postgressql query matching a field containing domainname

Need help with postsql query field matching a certain domain names in the end as per below in a particular FIELD.
1234.abc.xyz.com;
0971.abc.xyz.com
WHERE CAST (domain_name AS text) LIKE '%\d{4}.abc.xyz.com%'
#where domain_name is the FIELD name
~ is used for regular expression matching, LIKE for simple matching. Read more about them here: https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-SIMILARTO-REGEXP
If you just want to find domain_name that end in a particular text, the simple matching works fine (don't know if you really need the cast):
select * from tbl_test where domain_name LIKE '%.abc.xyz.com'
This will not work correctly:
select * from tbl_test where domain_name ~ '\d\d\d\d.abc.xyz.com'
The dot (.) is "any character" in a regular expression so this domain would be selected: abcd.abcxxyzdcom. You need to escape the dot in the string for it to be treated literally like this: '\d\d\d\d\.abc\.xyz\.com'
Underscore is a wildcard for "any character" in the simple LIKE.
use ~ followed by your search pattern as regular expression:
where domain_name ~ '\d\d\d\d\.abc\.xyz\.com'
playground:
https://dbfiddle.uk/O0Q_Ctmo
create table tbl_test (
domain_name varchar
);
insert into tbl_test VALUES
('1234.abc.xyz.com'),
('0971.abc.xyz.com'),
('0971.abc.xyz.bam'),
('1234.xxx.xyz.com'),
('123.xxx.xyz.com'),
('aaaa.xxx.xyz.com')
CREATE TABLE
INSERT 0 6
select * from tbl_test
where domain_name ~ '\d\d\d\d\.abc\.xyz\.com'
domain_name
1234.abc.xyz.com
0971.abc.xyz.com
SELECT 2
fiddle

Use ilike any() with escape character

In PostgreSQL you can do a case insensitive query with ILIKE:
select * from test where value ilike 'half is 50$%' escape '$'
And you can query multiple values at once by combining ILIKE with ANY()
select * from test where value ilike any(array['half is 50%', 'fifth is 20%'])
The query above will match 'Fifth is 2019', which I do not want, but when I try to use ILIKE and ANY() with an escape character I get a syntax error.
Am I missing something stupid, or is this simply not supported? If not, is there another way to query in a case insensitive way with multiple values at once?
EDIT: To clarify, the query will accept parameters through JDBC, so the actual SQL will look something like
select * from test where value ilike any(?) escape '$'
This is why I'm looking make % and _ from the user input be interpreted as literals.
The ESCAPE clause in ILIKE refers only to literals and does not apply to expressions. You should use a backslash, or if not possible, you can try:
with test(value) as (
values
('half is 50%'),
('half is 50x'),
('fifth is 20%'),
('fifth is 2000')
)
select *
from test
where value ilike any(select replace(unnest(array['half is 50$%', 'fifth is 20$%']), '$', '\'))
value
--------------
half is 50%
fifth is 20%
(2 rows)
Looks a bit clumsy but works well.
To match them as raw strings, you may use the ~* operator for insensitive match.
knayak=# select 'Half is 50%' ~* any(array['half is 50%', 'fifth is 20%'])
knayak-# ;
?column?
----------
t --True
(1 row)
knayak=# select 'fifth is 20' ~* any(array['half is 50%', 'fifth is 20%']);
?column?
----------
f --False
(1 row)
If you wish to escape the right hand operands of ilike use "escape" string constants, which are an extension to the SQL standard. An escape string constant is specified by writing the letter E (upper or lower case) just before the opening single quote
knayak=# select 'Half is 50%' ilike any(array[E'half is 50\\%', E'half is 20\\%'])
knayak-# ;
?column?
----------
t
(1 row)
DEMO

How to get substring from 4th occurence of a character until the end of given string in PSQL

Example
I have a string...
'/this/is/a/given/string/test.file'.
How can I get substring 'given/string/test.file' in PSQL?
Thank you!
You can use a regular expression
with example(str) as (
values('/this/is/a/given/string/test.file')
)
select regexp_replace(str, '(/.*?){4}', '')
from example;
regexp_replace
------------------------
given/string/test.file
(1 row)
or the function string_to_array():
select string_agg(word, '/' order by ord)
from example,
unnest(string_to_array(str, '/')) with ordinality as u(word, ord)
where ord > 4;
Read also How to find the 3rd occurrence of a pattern on a line.
I dont know how to get the nth occurence of a substring, but for this problem, you can use regular expression. Like this:
select substring('/this/is/a/given/string/test.file' from '/[^/]+/[^/]+/[^/]+/(.*)')
You can improve the regular expression, this is just for demo purpose.

Best way to search in postgres by a group of keyword

right now I have a keyword array like:
['key1', 'key2', 'key3'.......] , the keyword can be number or character.
If I want to search in my table (postgres database), and find out all record contain any of keyword in that array, how can I do that?
For example:
I got a table which has a column called name and a column called description
I need find all record that either name or description contains any keywords in that array.
thanks
Maybe this example will be useful:
CREATE TABLE TEST(
FIELD_KEY TEXT);
INSERT INTO TEST VALUES('this is hello');
INSERT INTO TEST VALUES('hello');
INSERT INTO TEST VALUES('this');
INSERT INTO TEST VALUES('other message');
SELECT *
FROM TEST
WHERE FIELD_KEY LIKE ANY (array['%this%', '%hel%']);
This will return:
this is hello
hello
this
Here other example:
SELECT *
FROM TEST
WHERE FIELD_KEY ~* 'this|HEL';
~* is case insensitive, ~ is case sensitive
You can try this example here.
select *
from t
where
array[name] <# my_array
or array[description] <# my_array
Couple the like operator with the any subquery expression:
select *
from t
where name like any (values ('%John%'), ('%Mary%'))
Or the array syntax:
where name like any (array['%John%', '%Mary%'])

handle escape sequence char in DB2

I want to search a column and get values where value containts \ .
I tried select * from "Values" where "ValueName" like '\'. But returns no value.
Also tried like "\" and like'\''%' etc. But no results.
See the DB2 Documentation on the LIKE predicate, in particular the parts about escape expressions.
What you want is
select * from Values where ValueName like '\\%' escape '\'
To give an example of usage:
create table backslash_escape_test
(
backslash_escape_test_column varchar(20)
);
insert into backslash_escape_test(backslash_escape_test_column)
values ('foo\');
insert into backslash_escape_test(backslash_escape_test_column)
values ('no slashes here');
insert into backslash_escape_test(backslash_escape_test_column)
values ('foo\bar');
insert into backslash_escape_test(backslash_escape_test_column)
values ('\bar');
select count(*) from backslash_escape_test where
backslash_escape_test_column like '%\\%' escape '\';
returns 3 (all 3 rows with \ in them).
select count(*) from backslash_escape_test where
backslash_escape_test_column like '\\%' escape '\';
returns 1 (the \bar row).
select * from Values where ValueName like '%\\%'
values is a not so good name because it may be confused with the values keyword
Don't escape it. You just need wildcards around it like this:
select count(*)
from escape_test
where test_column like '%\%'
But, suppose you really do need to escape the slash. Here's a simpler, more straightforward answer:
The escape-expression allows you to specify whatever character for escaping that you wish. So why use a character that you're looking for, thus requiring you to escape it? Use any other character instead. I'll use a plus sign as an example, but it could be a backslash, pound-sign, question-mark, anything other than a character you are looking for or one of the wildcard characters (% or _).
select count(*)
from escape_test
where test_column like '%\%' escape '+';
Now you don't have to add anything into your like-pattern.
To hold myself to the same standard of proof that #Michael demonstrated --
create table escape_test
( test_column varchar(20) );
insert into escape_test
(test_column)
values ('foo\'),
('no slashes here'),
('foo\bar'),
('\bar');
select 'test1' trial, count(*) result
from escape_test
where test_column like '%\%'
UNION
select 'test2', count(*)
from escape_test
where test_column like '%\\%' escape '\'
UNION
select 'test3', count(*)
from escape_test
where test_column like '%\%' escape '+'
;
Which returns the same number of rows for each method:
TRIAL RESULT
----- ------
test1 3
test2 3
test3 3