Not Understanding Where Statement - sql

I am new to SQL, I'm looking through some code for a small database for a medical office. What does the following mean and what will it do...Patient I get, its a field in the DB. This code is repeated for each of the fields.
WHERE ( LOWER ( "Patient" ) LIKE ( '%' || LOWER ( :Patient ) || '%' )

It does a case insensitive comparison looking for rows where the "Patient" column contains the substring passed in the :Patient parameter.
LOWER converts both sides to lower case.
|| is the ANSI SQL string concatenation operator.
% in a LIKE pattern is a wildcard meaning "match any set of zero or more characters".
So if :Patient was Smith the expression works out as
WHERE LOWER ( "Patient" ) LIKE '%smith%'

Related

Differene between 2 where conditions which looks similar

My mind is blind when I see those 2 where conditions and I can't understand what's the difference.
Can someone explain me? First returns 273 records and the second one returns 93. I thought they should return the same records.
1st
s.value LIKE '%One Travel%'
OR s.value LIKE '%One RSA%'
OR s.value LIKE '%One Other%'
OR s.value LIKE '%GP&U%'
OR s.value = ' '
2nd
s.value LIKE (
'%One Travel%'
,'%One RSA%'
,'%One Other%'
,'%GP&U%'
, ' ')
I don't know H2 at all, but I assume the second query evaluates to:
s.value LIKE '%One Travel%'
OR s.value LIKE '%One RSA%'
OR s.value LIKE '%One Other%'
OR s.value LIKE '%GP&U%'
OR s.value LIKE ' '
So you're left with the difference between s.value = ' ' and s.value LIKE ' '. Apparently H2 follows ANSI SQL, and the ANSI standard ignores trailing spaces in comparisons (actually the strings to be compared are padded with spaces till they are the same length). So s.value = ' ' returns TRUE for ' ', but also for '' and ' '. LIKE doesn't pad spaces to compare, since it is used for pattern matching rather than equality tests. Hence, LIKE ' ' only matches a single space.
In short; your first query returns more rows because rows where value is an empty string or multiple spaces, are also returned. Your second query returns only rows where value is a single space (ignoring the other conditions for simplicity).
LIKE in the second command is not a function, it is actually the same LIKE predicate. But its right-hand argument is specified as a row value.
I guess many DBMS throw an error, but H2 tries to convert all values here to a character string instead, in some rare cases it is useful, but in this case it isn't.
something LIKE (
'%One Travel%'
,'%One RSA%'
,'%One Other%'
,'%GP&U%'
, ' ')`
becomes
something LIKE 'ROW (%One Travel%, %One RSA%, %One Other%, %GP&U%, )'
in recent versions of H2 or
something LIKE '(%One Travel%, %One RSA%, %One Other%, %GP&U%, )'
in older versions (they don't support row values, but they treat such expressions as non-standard arrays).
Both expressions are meaningless. You need to use the first command with multiple OR conditions. Alternatively you can use a complex regular expression with non-standard REGEXP operator (with similar to LIKE syntax) or with also non-standard REGEXP_LIKE function.
Actually VALUE is a keyword, so both these commands cannot be executed by H2 (at least by its recent versions), but I assume it was just a replacement of a real column name.

Escape single quote in redshift sql in a column value

As per the attached image the column tlist in a table 'c' has values separated by a comma such as 'HCC19','HCC18'.
I am trying to used the column values in a query condition on redshift ..
where a.risk_factor in (c.tlist)
.. ..but its not giving the expected result possibly because its taking the value a single string as '
where a.risk_factor in( ' 'HCC19','HCC18' ') and not as required in the expression where a.risk_factor in('HCC19','HCC18')
Is there any workaround possible for this situation ?
You may try using a LIKE comparison here:
WHERE c.tlist LIKE '%''' || a.risk_factor || '''%';
The above LIKE expression compares 'HCC19','HCC18' searching for the single quoted risk factor. If the risk factor already comes with single quotes, then just use:
WHERE c.tlist LIKE '%' || a.risk_factor || '%';

SELECT if string contains column value

Manufacturer
==========================
id name
--------------------------
1 Company Inc.
2 Google Test.
3 3M (UNITY) USA. INC.
4 CE EE
Say, I have a string 'Google Test. 1257 SCS RANDOM 31233DD' and I want to find all rows in table manufacturer where ht name is part of the given string:
SELECT * FROM manufacturer
WHERE 'Google Test. 1257 SCS RANDOM 31233DD' ILIKE '%' || name || '%'
Correctly returns:
id name
--------------------------
2 Google Test.
But when I do:
SELECT * FROM manufacturer
WHERE '3dad QTICE EEN ' ILIKE '%' || name || '%'
it returns:
id name
--------------------------
4 CE EE
I don't want partial matches like this. The name shall not match in the middle of a word. I tried substring():
SELECT * from manufacturer
WHERE SUBSTRING('Google Test. 1257 SCS RANDOM 31233DD' from name) != '';
But I get:
ERROR: invalid regular expression: quantifier operand invalid
Unfortunately I don't have the exact spec to go off since I am querying this off external db. But from what I have seen, column is varchar(256). All values are upper cased and use plain spaces. All start with either character or number and end with either number, char, or special character. Ex: 'CLEVLAND DRILL (GREEN)'. There are special characters in the value, such as ,.()&/
I am not really looking for efficiency as long as it doesn't take over 50ms to do one query.
As of right now, there are about 10000+ entries but it could def grow over time.
One method with LIKE is to add spaces to the begining and end:
SELECT *
FROM db
WHERE ' ' || '3dad QTICE EEN ' || ' ' ILIKE '% ' || manufacturer || ' %'
If you need more sophisticated matching, then you might need to use regular expressions with word boundaries.
All the values start with either character or a number and end with either number, char, or special character. ... There are special characters in the value, such as ,.()&/.
I suggest the regular expression match operator ~. Carefully define boundaries and escape special characters in name:
Create once:
CREATE OR REPLACE FUNCTION f_regexp_escape(text)
RETURNS text AS
$func$
SELECT regexp_replace($1, '([!$()*+.:<=>?[\\\]^{|}-])', '\\\1', 'g')
$func$ LANGUAGE sql IMMUTABLE;
Then:
SELECT * FROM manufacturer
WHERE '3dad QTICE EEN ' ~ ('\m' || f_regexp_escape(name) || '( |$)')
How? Why?
\m .. beginning of a word. Works, since: values start with either character or number
( |$) .. a space or the end of the string. We need this since values: end with either number, char, or special character
The content of manufacturer.name is the core of the pattern. You want the literal meaning of all its characters, so strip any special meaning by escaping properly. This is true for LIKE (few special characters) as well as the regular expression match operator ~ (more special characters). Often overlooked and quite a pitfall. That got you (and the tricky definition of bounds). Read this!
Escape function for regular expression or LIKE patterns
And then use the function f_regexp_escape() as demonstrated. A name like:
3M (UNITY) USA. INC.
becomes:
3M \(UNITY\) USA\. INC\.
Might be convenient to store readily escaped patterns in table manufacturer, maybe as additional column. And maybe with added padding like this:
\m3M \(UNITY\) USA\. INC\.( |$)
Or generate the pattern on the fly like demonstrated.
This way name can be a single word or a whole phrase, and end with any characters. But start and end never match in the middle of a "word" on the other side.
There is an arsenal of other pattern matching tools in Postgres:
Pattern matching with LIKE, SIMILAR TO or regular expressions in PostgreSQL
If your table is big, consider the full text search infrastructure with optimized indexes and phrase search capability:
How to search hyphenated words in PostgreSQL full text search?
To solve this problem you really need to use regex, as adding a space either side of the string will not match at the beginning or end of the line. By using regex, we can check for that situation too. For example:
SELECT *
FROM manufacturer
WHERE 'Google Test. 1257 36700 SCS RANDOM WORD 31233DD' ~ ('(^| )' || name || '( |$)');
Output:
id name
2 Google Test.
Query:
SELECT *
FROM manufacturer
WHERE '3dad QTICE EEN ' ~ ('(^| )' || name || '( |$)');
Output:
There are no results to be displayed.
Query:
SELECT *
FROM manufacturer
WHERE 'CE EE ' ~ ('(^| )' || name || '( |$)');
Output:
id name
4 CE EE
Demo on dbfiddle
Update
Because the name values in the table can contain characters that have special meaning in a regex, they need to be escaped before the name is included into the regex. You can do this with REGEXP_REPLACE e.g.
REGEXP_REPLACE(name, '([\\.+*?[^\]$(){}=!<>|:\-#])', '\\\1', 'g')
So your query should be:
SELECT *
FROM manufacturer
WHERE 'Google Test. 1257 36700 SCS RANDOM WORD 31233DD' ~ ('(^| )' || REGEXP_REPLACE(name, '([\\.+*?[^\]$(){}=!<>|:\-#])', '\\\1', 'g') || '( |$)');
Updated demo

Postgres LIKE with column value as substring

I'm trying to compose a WHERE statement that will match rows where a column value is a substring of another string.
For example, I might have an event record with a name field of Edward Sharpe. I'd like to do something like:
SELECT * FROM events WHERE(name LIKE 'Edward Sharpe and the Magnetic Zeroes');
This doesn't work. I've also various permutations of:
SELECT * FROM events WHERE('%' || name || '%' LIKE 'Edward Sharpe and the Magnetic Zeroes');
Which also doesn't work.
Your second attempt is painfully close to correct. The LIKE keyword takes a string on its left, and a pattern on its right. Both can be expressions, but % only has a special meaning in the pattern to the right.
Try this:
SELECT * FROM events
WHERE name LIKE '%Edward Sharpe and the Magnetic Zeroes%';
Or rather this:
SELECT * FROM events
WHERE 'Edward Sharpe and the Magnetic Zeroes' LIKE '%' || name || '%';
Also note that all string operations in Postgres are case sensitive by default. To match a pattern ignoring case, use ILIKE in place of LIKE.

SQL 'LIKE' query using '%' where the search criteria contains '%'

I have an SQL query as below.
Select * from table
where name like '%' + search_criteria + '%'
If search_criteria = 'abc', it will return data containing xxxabcxxxx which is fine.
But if my search_criteria = 'abc%', it will still return data containing xxxabcxxx, which should not be the case.
How do I handle this situation?
If you want a % symbol in search_criteria to be treated as a literal character rather than as a wildcard, escape it to [%]
... where name like '%' + replace(search_criteria, '%', '[%]') + '%'
Use an escape clause:
select *
from (select '123abc456' AS result from dual
union all
select '123abc%456' AS result from dual
)
WHERE result LIKE '%abc\%%' escape '\'
Result
123abc%456
You can set your escape character to whatever you want. In this case, the default '\'. The escaped '\%' becomes a literal, the second '%' is not escaped, so again wild card.
See List of special characters for SQL LIKE clause
The easiest solution is to dispense with "like" altogether:
Select *
from table
where charindex(search_criteria, name) > 0
I prefer charindex over like. Historically, it had better performance, but I'm not sure if it makes much of difference now.
To escape a character in sql you can use !:
EXAMPLE - USING ESCAPE CHARACTERS
It is important to understand how to "Escape Characters" when pattern matching. These examples deal specifically with escaping characters in Oracle.
Let's say you wanted to search for a % or a _ character in the SQL LIKE condition. You can do this using an Escape character.
Please note that you can only define an escape character as a single character (length of 1).
For example:
SELECT *
FROM suppliers
WHERE supplier_name LIKE '!%' escape '!';
This SQL LIKE condition example identifies the ! character as an escape character. This statement will return all suppliers whose name is %.
Here is another more complicated example using escape characters in the SQL LIKE condition.
SELECT *
FROM suppliers
WHERE supplier_name LIKE 'H%!%' escape '!';
This SQL LIKE condition example returns all suppliers whose name starts with H and ends in %. For example, it would return a value such as 'Hello%'.
You can also use the escape character with the _ character in the SQL LIKE condition.
For example:
SELECT *
FROM suppliers
WHERE supplier_name LIKE 'H%!_' escape '!';
This SQL LIKE condition example returns all suppliers whose name starts with H and ends in _ . For example, it would return a value such as 'Hello_'.
Reference: sql/like
Select * from table where name like search_criteria
if you are expecting the user to add their own wildcards...
You need to escape it: on many databases this is done by preceding it with backslash, \%.
So abc becomes abc\%.
Your programming language will have a database-specific function to do this for you. For example, PHP has mysql_escape_string() for the MySQL database.
Escape the percent sign \% to make it part of your comparison value.
May be this one help :)
DECLARE #SearchCriteria VARCHAR(25)
SET #SearchCriteria = 'employee'
IF CHARINDEX('%', #SearchCriteria) = 0
BEGIN
SET #SearchCriteria = '%' + #SearchCriteria + '%'
END
SELECT *
FROM Employee
WHERE Name LIKE #SearchCriteria