Select query using ILIKE with the IN Statement - postgresql-9.5

I want to Query 3 columns for one string value but not be case sensitive. This is query I have started with. How do I use the ILIKE statement with below query?
SELECT * FROM poles WHERE 'Century Link' IN (attach1, attach2, attach3);

You can use the ANY operator on an array:
SELECT *
FROM poles
WHERE 'Century Link' ILIKE ANY (array[attach1, attach2, attach3]);

Related

How to Pass list of words into SQL 'LIKE' operator

Iam trying to pass a list of words into SQL Like operator.
The query is to return column called Customer Issue where Customer Issue matches any word in the above list.
my_list =['air con','no cold air','hot air','blowing hot air']
SELECT customer_comments
FROM table
where customer_comments like ('%air con%') #for single search
How do i pass my_list above?
Regular expression can help here. Other solution is using unnest. Which is given already.
SELECT customer_comments
FROM table
where REGEXP_CONTAINS(lower(customer_comments), r'air con|no cold air|hot air|blowing hot air');
A similiar question was answered on the following, works for SQL Server:
Combining "LIKE" and "IN" for SQL Server
Basically you'll have to chain a bunch of 'OR' conditions.
Based on the post #Jordi shared, I think below query can be an option in BigQuery.
query:
SELECT DISTINCT customer_comments
FROM sample,
UNNEST(['air con','no cold air','hot air','blowing hot air']) keyword
WHERE INSTR(customer_comments, keyword) <> 0;
output:
with sample:
CREATE TEMP TABLE sample AS
SELECT * FROM UNNEST(['air conditioner', 'cold air', 'too hot air']) customer_comments;
Consider below
with temp as (
select ['air con','no cold air','hot air','blowing hot air'] my_list
)
select customer_comments
from your_table, (
select string_agg(item, '|') list
from temp t, t.my_list item
)
where regexp_contains(customer_comments, r'' || list)
There are myriad ways to refactor above based on your specific use case - for example
select customer_comments
from your_table
where regexp_contains(customer_comments, r'' ||
array_to_string(['air con','no cold air','hot air','blowing hot air'], '|')
)

Checking if string has letter e (case insensitive) sql query using one where condition

I am practising on a website, where they ask me to show a list of players with an 'e' or 'E' in their name using only one WHERE condition.
My query shows the same output as what is expected, yet the website is saying 'I did something that is not right or result is incomplete'.
Does my WHERE statement count as one condition? Is there a way to be case insensitive only after the LIKE?
SELECT DISTINCT s.spelersnr, voorletters || ' ' || naam AS spelersnaam
FROM spelers s INNER JOIN wedstrijden w
ON s.spelersnr = w.spelersnr
WHERE LOWER(naam) LIKE '%e%'
ORDER BY s.spelersnr ASC
Assuming your database supports a LOWER function, then your current WHERE clause would already seem to be one condition:
WHERE LOWER(naam) LIKE '%e%'
In Postgres, you could also write this using SIMILAR TO:
WHERE naam SIMILAR TO '%(e|E)%'
Or, you could use a POSIX regular expression:
WHERE naam ~* '.*e.*'
as you mentioned it is postgres db, using similar to or like will help. a detailed explanation is in below link
https://dba.stackexchange.com/questions/10694/pattern-matching-with-like-similar-to-or-regular-expressions-in-postgresql
this will work:
SELECT DISTINCT s.spelersnr, voorletters || ' ' || naam AS spelersnaam
FROM spelers s INNER JOIN wedstrijden w
ON s.spelersnr = w.spelersnr
WHERE REGEXP_LIKE (naam, '(.)*e(.)*', 'i')
ORDER BY s.spelersnr ASC
The simplest way is to use ILIKE:
WHERE naam ILIKE '%e%'
This is built-in Postgres operator that does case-insensitive matching. This is explained in the documentation.

SQL special group by on list of strings ending with *

I would like to perform a "special group by" on strings with SQL language, some ending with "*". I use postgresql.
I can not clearly formulate this problem, even if I have partially solved it, with select, union and nested queries which are not elegant.
For exemple :
1) INPUT : I have a list of strings :
thestrings
varchar(9)
--------------
1000
1000-0001
1000-0002
2000*
2000-0001
2000-0002
3000*
3000-00*
3000-0001
3000-0002
2) OUTPUT : That I would like my "special group by" return :
1000
1000-0001
1000-0002
2000*
3000*
Because 2000-0001 and 2000-0002 are include in 2000*,
and because 3000-00*, 3000-0001 and 3000-0002 are includes in 3000*
3) SQL query I do :
SELECT every strings ending with *
UNION
SELECT every string where the begining NOT IN (SELECT every string ending with *) <-- with multiple inelegant left functions and NOT IN subqueries
4) That what I'm doing return :
1000
1000-0001
1000-0002
2000*
3000*
3000-00* <-- the problem
The problem is : 3000-00* staying in my result.
So my question is :
How can I generalize my problem? to remove all string who have a same begining string in the list (ending with *) ?
I think of regular expressions, but how to pass a list from a select in a regex ?
Thanks for help.
Select only strings for which no master string exists in the table:
select str
from mytable
where not exists
(
select *
from mytable master
where master.str like '%*'
and master.str <> mytable.str
and rtrim(mytable.str, '*') like rtrim(master.str, '*') || '%'
);
Assuming that only one general pattern can match any given string, the following should do what you want:
select coalesce(tpat.thestring, t.thestring) as thestring
from t left join
t tpat
on t.thestring like replace(tpat.thestring, '*', '%') and
t.thestring <> tpat.thestring
group by coalesce(tpat.thestring, t.thestring);
However, that is not your case. However, you can adjust this with distinct on:
select distinct on (t.thestring) coalesce(tpat.thestring, t.thestring)
from t left join
t tpat
on t.thestring like replace(tpat.thestring, '*', '%') and
t.thestring <> tpat.thestring
order by t.thestring, length(tpat.thestring)

Make table or database to be case insensitive

If I make a search for instance
"Candy" in where statement I retrieve 12 hits however if I write "candy" I retrieve 0 hits.
Is it possible to make the database or table to be case insensitive?
If yes, how?
Thank you
A simple solution might be to convert both the search string and the column you are searching on to lowercase using the LOWER() function in SQL Server. Something like:
SELECT whatever
FROM yourTable
WHERE LOWER(whatever) = LOWER(#searchString)
If you want to make your where clause case insensitive . convert left and right to the same case and then put condition .
If I take table as mytable with attributes X and Y . where filter is on Y then
select X , Y from mytable where UPPER(Y) = UPPER(#toSearch)
or
`select X , Y from mytable where LOWER(Y) = LOWER(#toSearch)`
In your case, maybe its easier to understand if i use your where clause ,example:
SELECT *
FROM yourTable
WHERE LOWER(whatever) = 'candy' or
SELECT *
FROM yourTable
WHERE UPPER(whatever) = 'CANDY'

MySQL LIKE IN()?

My current query looks like this:
SELECT * FROM fiberbox f WHERE f.fiberBox LIKE '%1740 %' OR f.fiberBox LIKE '%1938 %' OR f.fiberBox LIKE '%1940 %'
I did some looking around and can't find anything similar to a LIKE IN() - I envision it working like this:
SELECT * FROM fiberbox f WHERE f.fiberbox LIKE IN('%140 %', '%1938 %', '%1940 %')
Any ideas? Am I just thinking of the problem the wrong way - some obscure command I've never seen.
MySQL 5.0.77-community-log
A REGEXP might be more efficient, but you'd have to benchmark it to be sure, e.g.
SELECT * from fiberbox where field REGEXP '1740|1938|1940';
Paul Dixon's answer worked brilliantly for me. To add to this, here are some things I observed for those interested in using REGEXP:
To Accomplish multiple LIKE filters with Wildcards:
SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
OR field LIKE '%1938 %'
OR field LIKE '%1940 %';
Use REGEXP Alternative:
SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |1940 ';
Values within REGEXP quotes and between the | (OR) operator are treated as wildcards. Typically, REGEXP will require wildcard expressions such as (.*)1740 (.*) to work as %1740 %.
If you need more control over placement of the wildcard, use some of these variants:
To Accomplish LIKE with Controlled Wildcard Placement:
SELECT * FROM fiberbox WHERE field LIKE '1740 %'
OR field LIKE '%1938 '
OR field LIKE '%1940 % test';
Use:
SELECT * FROM fiberbox WHERE field REGEXP '^1740 |1938 $|1940 (.*) test';
Placing ^ in front of the value indicates start of the line.
Placing $ after the value indicates end of line.
Placing (.*) behaves much like the % wildcard.
The . indicates any single character, except line breaks. Placing .
inside () with * (.*) adds a repeating pattern indicating any number
of characters till end of line.
There are more efficient ways to narrow down specific matches, but that requires more review of Regular Expressions. NOTE: Not all regex patterns appear to work in MySQL statements. You'll need to test your patterns and see what works.
Finally, To Accomplish Multiple LIKE and NOT LIKE filters:
SELECT * FROM fiberbox WHERE field LIKE '%1740 %'
OR field LIKE '%1938 %'
OR field NOT LIKE '%1940 %'
OR field NOT LIKE 'test %'
OR field = '9999';
Use REGEXP Alternative:
SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 |^9999$'
OR field NOT REGEXP '1940 |^test ';
OR Mixed Alternative:
SELECT * FROM fiberbox WHERE field REGEXP '1740 |1938 '
OR field NOT REGEXP '1940 |^test '
OR field NOT LIKE 'test %'
OR field = '9999';
Notice I separated the NOT set in a separate WHERE filter. I experimented with using negating patterns, forward looking patterns, and so on. However, these expressions did not appear to yield the desired results. In the first example above, I use ^9999$ to indicate exact match. This allows you to add specific matches with wildcard matches in the same expression. However, you can also mix these types of statements as you can see in the second example listed.
Regarding performance, I ran some minor tests against an existing table and found no differences between my variations. However, I imagine performance could be an issue with bigger databases, larger fields, greater record counts, and more complex filters.
As always, use logic above as it makes sense.
If you want to learn more about regular expressions, I recommend www.regular-expressions.info as a good reference site.
Regexp way with list of values
SELECT * FROM table WHERE field regexp concat_ws("|",
"111",
"222",
"333");
You can create an inline view or a temporary table, fill it with you values and issue this:
SELECT *
FROM fiberbox f
JOIN (
SELECT '%1740%' AS cond
UNION ALL
SELECT '%1938%' AS cond
UNION ALL
SELECT '%1940%' AS cond
) с
ON f.fiberBox LIKE cond
This, however, can return you multiple rows for a fiberbox that is something like '1740, 1938', so this query can fit you better:
SELECT *
FROM fiberbox f
WHERE EXISTS
(
SELECT 1
FROM (
SELECT '%1740%' AS cond
UNION ALL
SELECT '%1938%' AS cond
UNION ALL
SELECT '%1940%' AS cond
) с
WHERE f.fiberbox LIKE cond
)
Sorry, there is no operation similar to LIKE IN in mysql.
If you want to use the LIKE operator without a join, you'll have to do it this way:
(field LIKE value OR field LIKE value OR field LIKE value)
You know, MySQL will not optimize that query, FYI.
Just note to anyone trying the REGEXP to use "LIKE IN" functionality.
IN allows you to do:
field IN (
'val1',
'val2',
'val3'
)
In REGEXP this won't work
REGEXP '
val1$|
val2$|
val3$
'
It has to be in one line like this:
REGEXP 'val1$|val2$|val3$'
This would be correct:
SELECT * FROM table WHERE field regexp concat_ws("|",(
"111",
"222",
"333"
));
Flip operands
'a,b,c' like '%'||field||'%'
Just a little tip:
I prefer to use the variant RLIKE (exactly the same command as REGEXP) as it sounds more like natural language, and is shorter; well, just 1 char.
The "R" prefix is for Reg. Exp., of course.
You can get desired result with help of Regular Expressions.
SELECT fiberbox from fiberbox where fiberbox REGEXP '[1740|1938|1940]';
We can test the above query please click SQL fiddle
SELECT fiberbox from fiberbox where fiberbox REGEXP '[174019381940]';
We can test the above query please click SQL fiddle
You can use like this too:
SELECT
*
FROM
fiberbox f
JOIN (
SELECT
substring_index( substring_index( '1740,1938,1940', ',', help_topic_id + 1 ), ',',- 1 ) AS sub_
FROM
mysql.help_topic
WHERE
help_topic_id <(
length( '1740,1938,1940' )- length(
REPLACE ( '1740,1938,1940', ',', '' ))+ 1
) AS b
) ON f.fiberBox LIKE concat('%',
b.sub_,
'%')
You can use like this too:
SELECT * FROM fiberbox WHERE fiber IN('140 ', '1938 ', '1940 ')