Postgresql select where array overlaps using like - sql

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 || '%';

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 || '%'
);

Filtering out values inside the field using SQL command

I have one table as below:
And I have another table as below:
Now, I want to filter out the image name from table 1-image description field and compare it with image name in the table 2 and return the image ID in the output table. So I want my output table like below:
Could someone please help on this.
You can use substring_index(). Assuming it is the last value:
select substring_index(image_description, 'image=', -1)
from t;
If it can be anywhere in a semicolon separated list:
select substring_index(substring_index(image_description, 'image=', -1), ';', 1)
from t;
Here is a db<>fiddle.
EDIT:
In Oracle, you would simply use regexp_replace():
select regexp_replace(image_description, '^.*image=([^;]+).*', '\1')
from t;
Here is a db<>fiddle for this version.
The rest is simply joining on the values.
It looks like you are using Oracle and not MySql, so try this query with a left join of table1 to table2 and the operator like:
select t1.Name, t2."image id"
from table1 t1 left join table2 t2
on t1."image description" like '%image="' || t2.image || '" />'
This will work for the sample data as you posted it, but if image="..." may appear anywhere inside the string then use:
on t1."image description" like '%image="' || t2.image || '"%'
See the demo.
Results:
> NAME | image id
> :--- | -------:
> x | 1
> b | null
> y | 2
> z | 2
> a | null
Assuming the values for column image_desc has always the same format that ends with the text pattern image=...., the following would work.
SELECT SUBSTR(image_desc, LOCATE('image=', image_desc) + 6) AS image
FROM images;
if your image description content pattern is always the same and the value youa are looking for is at the right od the = char
then you could check for the right part after the = char this way
For mysql
select SUBSTRING_INDEX(your_column_name,'=',-1)
from your_table
where your_column_name like '%image%';
for Oracle you could use
SUBSTR(youc_col, INSTR(you_col, '=') + 1)
select SUBSTR(youc_col, INSTR(you_col, '=') + 1)
from your_table
where your_column_name like '%image%';

SELECT with lower case + unaccent + multiple columns in PostgreSQL

Table schools
id | address | name
1 | Rybničná 59, Bratislava | Stredná odborná škola elektrotechnická
2 | Ul. Sibírska 1, Trnava | Stredná odborná škola elektrotechnická
What I want
From client If I want to type:
Stredná odborná
stredná odborná
stredna odborna
It must find rows with id 1 and 2
If I want to type Bratislava or bratis It must find row with id 1
What I have
SELECT * FROM schools WHERE unaccent(address) LIKE ('%' || 'bratis' || '%');
I need to select from 2 columns (address and name)
To make the search case insentive, use ILIKE instead of LIKE. Then, you would want to remove the accents from the input string as well. At last, just use AND or OR to combine the two criteria (note that you could use the same search term for both columns - use OR in this case)
SELECT * FROM schools
WHERE unaccent(address) ILIKE ('%' || unaccent('bratis') || '%')
AND unaccent(name) ILIKE ('%' || unaccent('Stredná odborná') || '%')
I hope this works
SELECT * FROM schools
WHERE unaccent(address|| ' ' ||name) ILIKE ('%' || 'bratis' || '%');

Merge multiple rows in a single

I need merge multiple rows in a single row with data concatenated on the columns.
This three lines are result is from my query with INNER JOIN
Name | SC | Type
----------------------
name1 | 121212 | type1
name2 | 123456 | null
name3 | null | type1
I want display result like this:
Name | SC | Type
----------------------
name1; 121212; type1;
name2; 123456; ;
name3; ; type1;
It's a single row, each column with data concatenated with ; and a \n in the end of each data.
The final query need run in SQL Server and Oracle.
I honestly doubt you can use the same query in both oracle and SQL-Server since they both have different functions when it comes to dealing with null values.
For Oracle:
SELECT NVL(Name,'') || ';' as name,
NVL(SC,'') || ';' as SC,
NVL(type,'') || ';' as type
FROM (YourQueryHere)
For SQL-Server
SELECT isnull(Name,'') + ';' as name,
isnull(SC,'') + ';' as SC,
isnull(type,'') + ';' as type
FROM (YourQueryHere)
Note that as #jarlh said, in concatenating side you can use concat(value,value2) which should work both on SQL-Server and Oracle, depending on your version.
You could simply concatenate the fields:
SELECT ISNULL(Name,'') + ';' as Name,
ISNULL(SC, '') + ';' as SC,
ISNULL(Type, '') + ';' as Type
FROM
(
-- whatever is your query goes here...
);

SELECT values by another table with predefined regular expression

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.