SELECT values by another table with predefined regular expression - sql

I would like to select rows in my table by my another table with my predefined regular expressions.
Below you can see my example tables:
Table code
id | codename
-----+------------
1 | 123456
2 | NF123
3 | AAA444
4 | EEE123
5 | EEE423
6 | AB123E
Table validcode
id | validreg
------+-----------
1 | [E]{3}[0-9]{3}
2 | NF123
And here is the test case on sqlfidlle.
This is one of the my select statements I tried, but it doesn't work:
SELECT n.codename FROM code n
WHERE EXISTS (SELECT * FROM validcode WHERE n.codename ~* E'^' || validreg || '$');
I get this error:
ERROR: argument of WHERE must be type boolean, not type text:
SELECT codename FROM code n WHERE EXISTS (SELECT * FROM validcode WHERE n.codename ~* E'^' || validreg || '$');
Is possible to do this somehow?

SELECT n.codename FROM code n, validcode
WHERE n.codename ~* ('^' || validcode.validreg || '$')
Braces because otherwise the parser thinks that n.codename ~* E'^' is one part and to that concatenates the rest.
Also your original query would work with the additional braces.

Related

SQL query value (more char) longer then actual value in table

I'm trying to query with Postgres a value where my query string (value) has more char than the actual value in the column:
| id | firstName|
|:---| :--------|
| 1 | bee |
| 2 | beeWaxer |
so for example if I query beeWax, because beeWax has bee inside it I would like it to return also bee and also beeWaxer.
if I use a ILIKE operator it will only return beeWaxer (obviously):
SELECT * FROM table WHERE firstName ILIKE '%beeWax%';
is there a query that will return both rows?
It seems you want a LIKEin both directions: Show all names that include the search word and all names that are included in the search word. Something along the lines of:
SELECT *
FROM table
WHERE firstName ILIKE '%' || :searchword || '%'
OR :searchword ILIKE '%' || firstName || '%';
I agree with the existing answer, but if you want a little cleaner code you can also use the case insensitive regex:
SELECT *
FROM table
WHERE firstName ~* 'beeWax' or 'beeWax' ~* firstname
You can check if the firstname is like each row in column firstname
select *
from table x
where exists (
select 1 from table y
where 'beeWax' like '%' || x.firstName || '%'
);

Oracle regex to extract string between first pair of < and > brackets

I am have been assigned a task to parse a string (which is essentially in XML format) and I need to extract the name of the first tag in the string
eg: string '<column><data-type>string</data-type>.............'
or '<filter><condition>....</condition>...............'
or
'......................'
the string keeps changing but I am only interested in the first tag, I would like to get the output like:
column,
filter,
query
i have tried regexp_substr(string,'^<(.+)>',1,1,null,1) and some similer variations but they don't seem to be working cosistently.
Please help.
If you have XML data then use a proper XML parser:
SELECT XMLQUERY( '/*/name()' PASSING XMLTYPE(value) RETURNING CONTENT ) AS tag_name
FROM table_name
Which for the sample data:
CREATE TABLE table_name ( value CLOB );
INSERT INTO table_name ( value )
SELECT '<column><data-type>string</data-type></column>' FROM DUAL UNION ALL
SELECT '<filter><condition>....</condition></filter>' FROM DUAL UNION ALL
SELECT '<query />' FROM DUAL UNION ALL
SELECT '<has_attributes attr1="do not return this" attr2="<or> this" />' FROM DUAL
Outputs:
| TAG_NAME |
| :------------- |
| column |
| filter |
| query |
| has_attributes |
db<>fiddle here
You are looking for any character between the bounds -- and that includes '>'. So, just exclude the terminating character:
select regexp_substr(string,'^<([^>]+)>',1,1,null,1)
from (select '<column><data-type>string</data-type>.............' as string from dual union all
select '<filter><condition>....</condition>...............' from dual
) x;

oracle sql contain

I have table with values in columns like
colname
TMC_MCH,OTA_MCH,CONSOL_MCH,RETAIL_MCH,TOUROP_MCH,SPEC_MCH,QRACTO_MCH
RETAIL_MCH
RETAIL_MCH,CONSOL_MCH
CONSOL_MCH
OTA_MCH
I need to run query to fetch all rows contains RETAIL_MCH or CONSOL_MCH.
if i run query below i get result as below
select * from table111 where
(CONTAINS(table111.colname, 'RETAIL,CONSOL' , 1) > 0)
TMC_MCH,OTA_MCH,CONSOL_MCH,RETAIL_MCH,TOUROP_MCH,SPEC_MCH,QRACTO_MCH
RETAIL_MCH
RETAIL_MCH,CONSOL_MCH
CONSOL_MCH
but I need to exact search including underscore "_"
select * from table111 where
(CONTAINS(table111.colname, 'RETAIL_MCH,CONSOL_MCH' , 1) > 0)
CONTAINS is an Oracle text function, you can escape the underscore:
SELECT *
FROM table111
WHERE CONTAINS( colname, 'RETAIL\_MCH,CONSOL\_MCH', 1 ) > 0
Or, if you want to pass the string in unescaped then you could use REPLACE to add the escape characters:
SELECT *
FROM table111
WHERE CONTAINS( colname, REPLACE ( 'RETAIL_MCH,CONSOL_MCH', '_', '\_' ), 1 ) > 0
Which, for the sample data:
CREATE TABLE table111 ( colname ) AS
SELECT 'TMC_MCH,OTA_MCH,CONSOL_MCH,RETAIL_MCH,TOUROP_MCH,SPEC_MCH,QRACTO_MCH' FROM DUAL UNION ALL
SELECT 'RETAIL_MCH' FROM DUAL UNION ALL
SELECT 'RETAIL_MCH,CONSOL_MCH' FROM DUAL UNION ALL
SELECT 'CONSOL_MCH' FROM DUAL UNION ALL
SELECT 'OTA_MCH' FROM DUAL;
CREATE INDEX table111__colname__textidx ON table111(colname) INDEXTYPE IS CTXSYS.CONTEXT;
Outputs:
| COLNAME |
| :------------------------------------------------------------------- |
| TMC_MCH,OTA_MCH,CONSOL_MCH,RETAIL_MCH,TOUROP_MCH,SPEC_MCH,QRACTO_MCH |
| RETAIL_MCH |
| RETAIL_MCH,CONSOL_MCH |
| CONSOL_MCH |
db<>fiddle here
It would be probably simpler if you said which result you want. The way I understood it, maybe this helps:
select *
from table111
where instr(colname, 'RETAIL_MCH') > 0
or instr(colname, 'CONSOL_MCH') > 0;
OR might need to be substituted by AND (depending on what you want).
If you want either value, you would use:
where CONTAINS(table111.colname, 'RETAIL|CONSOL' , 1) > 0
If you want both:
where CONTAINS(table111.colname, 'RETAIL&CONSOL' , 1) > 0
You should pass the value in with the operator you want, instead of ,.

Postgresql select where array overlaps using like

Is it possible to determine if an ARRAY column contains overlapping values from another array with the LIKE clause?
The && operator works but the strings have to be exact matches
q = """select * from articles where keywords && '{"mortgage brokers"}';""" // Exact match
Is it possible to filter the keywords where rows contain values with substring, not the full string? Something like:
q = """select * from articles where keywords && LIKE '{"mortgage"}';""" // HOW TO FILTER keywords containing value with substring
LIKE operates on strings. To check whether two arrays overlap, you can use &&.
From the Array Functions and Operators documentation:
&& : overlap (have elements in common)
SELECT ARRAY[1,4,3] && ARRAY[2,1] arrays_overlap;
| arrays_overlap |
| -------------- |
| true |
To see if there are values in an array that are LIKE those from another array, one solution would be to unnest both arrays and compare the results with LIKE:
SELECT EXISTS (
SELECT 1
FROM
unnest(ARRAY['abc', 'def' ]) my_array(x)
INNER JOIN unnest (ARRAY['a', 'z' ]) my_keywords(x)
ON my_array.x LIKE '%' || my_keywords.x || '%'
) arrays_have_similar_elements;
| arrays_have_similar_elements |
| ---------------------------- |
| true |
SELECT EXISTS (
SELECT 1
FROM
unnest(ARRAY['abc', 'def' ]) my_array(x)
INNER JOIN unnest (ARRAY['y', 'z' ]) my_keywords(x)
ON my_array.x LIKE '%' || my_keywords.x || '%'
) arrays_have_similar_elements;
| arrays_have_similar_elements |
| ---------------------------- |
| false |
Demo on DB Fiddle
Thanks to #GMB for the guidance. I was able to solve the problem using the query below.
SELECT * from articles, unnest(keywords) my_array(x)
INNER JOIN unnest(ARRAY['broker']) my_keywords(x)
ON my_array.x LIKE '%' || my_keywords.x || '%';

Set plsql parameters partially

I need to create a query that when i enter partially the value of a parameter until"/" is shown it displays all the row sequences with that parameter in the first part before "/"
I enter as a parameter: pwd
The result of query should be:
pwd/1
pwd/2
pwd/3....
If you have a bind variable :parameter then:
SELECT *
FROM table_name
WHERE value LIKE :parameter || '/%'
So for some test data:
CREATE TABLE table_name ( id, value ) AS
SELECT 1, 'pwd/1' FROM DUAL UNION ALL
SELECT 2, 'pwd/2' FROM DUAL UNION ALL
SELECT 3, 'pwdtest/1' FROM DUAL;
If :parameter is pwd then the output is:
ID | VALUE
-: | :----
1 | pwd/1
2 | pwd/2
db<>fiddle here