SQL select query with wildcard on input parameter - sql

Same question as my other thread basically!
I have a db table and I need to write a query that will return results based on a partial match of a string.
Example:
DB field: abc
Search term: 123abc
i.e. I want given 123abc for it to return the row that has the abc field in it!
My attempt:
SELECT mood from users where '$searchTerm' like '%' || dbField
Is something like that possible in any way?
Well basically I'm trying to match the numbers with the search term la77740985
id | mood | numberfield
==== ===== ============
1 bad '77740985'
2 good '77513755'
Running the query returns both rows!
Note: The wildcard should only be in the beginning of the string in other words I want the search term to begin with anything but still match the string from the database that basically have the same ending.

It worked like this:
SELECT mood from users where '$searchTerm' like concat('%',numberField);

SELECT mood
from users
where '$searchTerm' like '%' || numberField
This will match $searchTerm = '123abc' against dbField that contains 'abc'. It's correct. If you need contains (anywhere), then add || '%' at the end.
Full test script
drop table if exists users2;
create table users2 (mood, numberfield);
insert into users2(mood,numberfield) values ('happy','77740985');
insert into users2(mood,numberfield) values ('sad','77513755');
Then run this
SELECT mood from users2 where 'la77740985' like ('%' || numberfield);
Output
mood
=======
'happy'

Related

How to return 0 with where condition user when user search only space character?

Hello I'm using Oracle 11g and i have a data that looks like this
no|name|flag
------------
1|kumar|1
2|rajesh singh|1
3|adi sneedar|1
4|danielle castro|1
5|cef danish|1
if i did
select count(*) from tablename where name like '% %'
it will return 2 records.
if i did "multiple spaces", like 2 or more spaces
select count(*) from tablename where name like '% %'
it returns 0(this means good)
it will return 5 records.
What i want is if the user only input '% %' it will also return 0. But i also wanted that
select count(*) from tablename where name like '%adi sneedar%'
it will return 1
How should i do that in the where condition?
Something like this might suffice, assuming that the '%' are being passed as part of the binding input
select *
from mytable
where name like :bindvar
and replace(replace(:bindvar,'%'),' ') is not null
which basically says they need to enter something that is not solely spaces and percentage signs.

how to skip particular character(s) in SQL LIKE query

I have a table(say users) in which there is a column say name.
you may think table structure a shown below:
-------------
name
--------------
Abdul Khalid
--------------
Abdul, Khalid
--------------
Abdul - Khalid
--------------
other names
My question is can I do some query to find all the 3 rows in which the name column value is "Abdul Khalid"(basically "Abdul Khalid" or "Abdul, Khalid" or "Abdul - Khalid" if I skip the "," and "-" character).
You can use like:
select t.*
from t
where name like 'Abdul%Khalid';
If you want the names anywhere in the string (but in that order), then put wildcards at the beginning:
select t.*
from t
where name like '%Abdul%Khalid%';
If you are passing in the value as a variable:
select t.*
from t
where name like replace('Abdul Khalid', ' ', '%');
For PostgreSQL is better to use '~'
name ~ '^Abdul[ ,-]Khalid$'
OR if you want also in middle of string:
name ~ 'Abdul[ ,-]Khalid'
Or you can use translate (with index on it) for any SQL:
translate(name, ' ,-') = 'AbdulKhalid'
you also can use REGEXP like this:
SELECT * from yourTable where name REGEXP 'Abdul( |, | - )Khalid';

How to match a column value against a string of any length?

I have a table which stores company names and their homepage URLs. Like so:
CompanyName | CompanyURL
WalMart walmart.com
eBay UK www.ebay.co.uk
Amazon http://www.amazon.com
Sometimes people will submit a URL to my application such as http://www.ebay.co.uk/amazon
I want to see if the CompanyURL value is contained within the URL submitted by the user.
I would normally try to do this:
SELECT
*
FROM
dbo.Company
WHERE CompanyURL LIKE '%www.ebay.co.uk/amazonstore%'
Naturally the above won't work because the string is longer than the column value. What I'm really trying to accomplish is:
...
WHERE CompanyURL IS CONTAINED SOMEHWERE INSIDE 'www.ebay.co.uk/amazonstore' --- the URL provided by the user
Is is possible to do this in SQL Server 2014?
Declare #YourTable table (CompanyName varchar(50),CompanyURL varchar(50))
Insert Into #YourTable values
('WalMart','walmart.com'),
('eBay UK','ebay.co.uk'),
('Amazon','http://www.amazon.com')
Select *
From #YourTable
Where 'www.ebay.co.uk/amazonstore' like '%'+Replace(Replace(Replace(Replace(CompanyURL,'//',''),'http:',''),'https:',''),'www','')+'%'
Returns
CompanyName CompanyURL
eBay UK ebay.co.uk
Now, I would recommend that you normalize your CompanyURL data.
Update YourTable set CompanyURL = Replace(Replace(Replace(Replace(CompanyURL,'//',''),'http:',''),'https:',''),'www','')
So future searches would only be
Select *
From #YourTable
Where 'www.ebay.co.uk/amazonstore' like '%'+CompanyURL+'%'
You could use CHARINDEX, which avoids dealing with the messy % symbol (which has a special meaning in a URL).
If you are expecting the input to be a superstring of the CompanyURL in your table (i.e. you want to see if the supplied value contains a CompanyURL), use this:
WHERE CHARINDEX(CompanyURL, 'www.ebay.co.uk/amazonstore') != 0
If you are expecting the input to be a substring of the CompanyURL in your table (i.e. you want to see if any of your CompanyURL values contains the supplied value), use this:
WHERE CHARINDEX('www.ebay.co.uk/amazonstore', CompanyURL) != 0
If you need to detect both conditions, you can always use this
WHERE CHARINDEX('www.ebay.co.uk/amazonstore', CompanyURL) != 0
OR CHARINDEX(CompanyURL, 'www.ebay.co.uk/amazonstore') != 0
...although you may end up with some false positives depending how strict you are about the input and the values in your table.
You have the like backwards:
WHERE 'www.ebay.co.uk/amazonstore' like '%' + CompanyURL + '%'
Why not compare like this
SELECT *
FROM
dbo.Company
WHERE 'www.ebay.co.uk/amazonstore' LIKE '%'+ CompanyURL +'%' OR
CompanyURL LIKE '%www.ebay.co.uk/amazonstore%'

Is it possible to query a comma separated column for a specific value?

I have (and don't own, so I can't change) a table with a layout similar to this.
ID | CATEGORIES
---------------
1 | c1
2 | c2,c3
3 | c3,c2
4 | c3
5 | c4,c8,c5,c100
I need to return the rows that contain a specific category id. I starting by writing the queries with LIKE statements, because the values can be anywhere in the string
SELECT id FROM table WHERE categories LIKE '%c2%';
Would return rows 2 and 3
SELECT id FROM table WHERE categories LIKE '%c3%' and categories LIKE '%c2%'; Would again get me rows 2 and 3, but not row 4
SELECT id FROM table WHERE categories LIKE '%c3%' or categories LIKE '%c2%'; Would again get me rows 2, 3, and 4
I don't like all the LIKE statements. I've found FIND_IN_SET() in the Oracle documentation but it doesn't seem to work in 10g. I get the following error:
ORA-00904: "FIND_IN_SET": invalid identifier
00904. 00000 - "%s: invalid identifier"
when running this query: SELECT id FROM table WHERE FIND_IN_SET('c2', categories); (example from the docs) or this query: SELECT id FROM table WHERE FIND_IN_SET('c2', categories) <> 0; (example from Google)
I would expect it to return rows 2 and 3.
Is there a better way to write these queries instead of using a ton of LIKE statements?
You can, using LIKE. You don't want to match for partial values, so you'll have to include the commas in your search. That also means that you'll have to provide an extra comma to search for values at the beginning or end of your text:
select
*
from
YourTable
where
',' || CommaSeparatedValueColumn || ',' LIKE '%,SearchValue,%'
But this query will be slow, as will all queries using LIKE, especially with a leading wildcard.
And there's always a risk. If there are spaces around the values, or values can contain commas themselves in which case they are surrounded by quotes (like in csv files), this query won't work and you'll have to add even more logic, slowing down your query even more.
A better solution would be to add a child table for these categories. Or rather even a separate table for the catagories, and a table that cross links them to YourTable.
You can write a PIPELINED table function which return a 1 column table. Each row is a value from the comma separated string. Use something like this to pop a string from the list and put it as a row into the table:
PIPE ROW(ltrim(rtrim(substr(l_list, 1, l_idx - 1),' '),' '));
Usage:
SELECT * FROM MyTable
WHERE 'c2' IN TABLE(Util_Pkg.split_string(categories));
See more here: Oracle docs
Yes and No...
"Yes":
Normalize the data (strongly recommended) - i.e. split the categorie column so that you have each categorie in a separate... then you can just query it in a normal faschion...
"No":
As long as you keep this "pseudo-structure" there will be several issues (performance and others) and you will have to do something similar to:
SELECT * FROM MyTable WHERE categories LIKE 'c2,%' OR categories = 'c2' OR categories LIKE '%,c2,%' OR categories LIKE '%,c2'
IF you absolutely must you could define a function which is named FIND_IN_SET like the following:
CREATE OR REPLACE Function FIND_IN_SET
( vSET IN varchar2, vToFind IN VARCHAR2 )
RETURN number
IS
rRESULT number;
BEGIN
rRESULT := -1;
SELECT COUNT(*) INTO rRESULT FROM DUAL WHERE vSET LIKE ( vToFine || ',%' ) OR vSET = vToFind OR vSET LIKE ('%,' || vToFind || ',%') OR vSET LIKE ('%,' || vToFind);
RETURN rRESULT;
END;
You can then use that function like:
SELECT * FROM MyTable WHERE FIND_IN_SET (categories, 'c2' ) > 0;
For the sake of future searchers, don't forget the regular expression way:
with tbl as (
select 1 ID, 'c1' CATEGORIES from dual
union
select 2 ID, 'c2,c3' CATEGORIES from dual
union
select 3 ID, 'c3,c2' CATEGORIES from dual
union
select 4 ID, 'c3' CATEGORIES from dual
union
select 5 ID, 'c4,c8,c5,c100' CATEGORIES from dual
)
select *
from tbl
where regexp_like(CATEGORIES, '(^|\W)c3(\W|$)');
ID CATEGORIES
---------- -------------
2 c2,c3
3 c3,c2
4 c3
This matches on a word boundary, so even if the comma was followed by a space it would still work. If you want to be more strict and match only where a comma separates values, replace the '\W' with a comma. At any rate, read the regular expression as:
match a group of either the beginning of the line or a word boundary, followed by the target search value, followed by a group of either a word boundary or the end of the line.
As long as the comma-delimited list is 512 characters or less, you can also use a regular expression in this instance (Oracle's regular expression functions, e.g., REGEXP_LIKE(), are limited to 512 characters):
SELECT id, categories
FROM mytable
WHERE REGEXP_LIKE('c2', '^(' || REPLACE(categories, ',', '|') || ')$', 'i');
In the above I'm replacing the commas with the regular expression alternation operator |. If your list of delimited values is already |-delimited, so much the better.

Mysql query with wildcard on number strings

I am trying to query a mysql table which contains strings of numbers
(i.e. '1,2,3,4,5').
How do I search to see if it has '1' but not '11' bearing in mind if it is '9,10' '9%' doesnt work??
Fixed!
(field like '10' OR field like '%,10,%' OR field like '%,10' OR field like '10,%')
You could try the function find_in_set
select find_in_set('1','1,2,3,11,12')
You need the function FIND_IN_SET. Btw, '9%' should work, if the column contains the values you specified, are you sure you're querying
SELECT * FROM table WHERE field LIKE '9%'?
Standard SQL can do it as well:
...
WHERE
',' + SetValue + ',' LIKE '%,1,%'
AND ',' + SetValue + ',' NOT LIKE '%,11,%'
This expression cannot make use of an index, therefore performance will degrade quickly as the table size rises.
For better performance your table should be properly normalized, e.g.
SetId SetValue
1 1
1 2
1 3
1 4
1 5
instead of
SetId SetValue
1 '1,2,3,4,5'