tags:

views:

136

answers:

5

I want to grab from a db a record with name='John Doe'.

I'd like my query to also grab 'John(4 spaces between)Doe','John(2 spaces betwewen)Doe' etc. (at least one space however).

I'd also like that the case won't matter, so I can also get 'John Doe' by typing 'john doe' etc.

+2  A: 

Try this:

SELECT * FROM table WHERE lower(NAME) like 'john%doe%'

use like with wildcards (e.g. %) to get around the spaces and the lower (orlcase) to be case insensitive.

EDIT:
As the commenters pointed out, there are two shortcomings within this solution.

First: you will select "johnny doe" or worse "john Eldoe", or worse, "john Macadoelt" with this query, so you'll need extra filtering on the application side.

Second: using a function can lead to table scans instead of index scans. This may be avoided, if your dbms supports function based indexes. See this Oracle example

Tim Büthe
Attention, however, this will also yield entries like "johnny doe" or worse "john Eldoe", or worse, "john Macadoelt" etc..
mjv
Adding a space on either side of the first % will solve some of the problems mentioned however.
mjv
@mjv: excellent point, probably best to replace all spaces with empty strings and compare with 'johndoe'
kurosch
Another suggestion (if applicable/possible) is to have the underlying table/column be case insensitive, _at the level of SQL_, hence avoiding the lower() call, which has many negative effects on the query performance (including the possible need to scan the whole table / index, depending on specific dbms/version)
mjv
@kurosch yes/right (of sorts...) I noted that my idea of the % on either side may disqualify the good boy on the block i.e. the normalized "john doe" (only one space not two!). On the other hand, your suggestion to remove all spaces is both computationally expensive (and further cause scans), as well as semantically wrong: ex: `"Alric Hardson"` vs. '"AlRichard Son"` vs. `"Al Richardson"` These "simple ones" can be tricky can't they ;-)
mjv
While we're at it, might as well point out that storing first_name and last_name as separate uppercase fields is a pretty standard way to avoid all of these problems.
kurosch
You always could do more filtering within the application, so fetching to much results is better then fetching to few. Secondly: yes, using a function can lead to table scans instead of indexes. To get around this, you might create a function based index for this.
Tim Büthe
+1  A: 

In sql you can use wildcards, that is a character that stands in place of other characters. for example:

select * from table where name like 'john%doe'

will select all names that start with john and end with doe no matter how many characters in between.

This article explains more and gives some options.

Vincent Ramdhanie
Great answer. 10x!
As with the accepted answer, be aware this will also return a lot of results you might not be expecting (john mordoe, for example)
mavnn
+2  A: 

If your database has Replace function

Select * From Table
Where Upper(Replace(name, ' ', '')) = 'JOHNDOE'

The rest of these will return rows where the middle part between John and Doe is anything, not just spaces...

if your database has left function and Reverse, Try either

Select * From Table
Where left(Upper(name), 4) = 'JOHN' 
   And Left(Reverse(Upper(name), 3)) = 'EOD'

else use substring and reverse

Select * From Table
Where substring(Upper(name), 4) = 'JOHN' 
   And substring(Reverse(Upper(name), 3)) = 'EOD'

or Like operator

Select * From Table
Where Upper(name) Like 'JOHN%DOE'
Charles Bretana
+1  A: 

The wildcard will match on zero characters, so if you want at least one space then you should do

select * from table where lower(name) like 'john %doe'
kurosch
That will also match 'John Uberdoe'.
Jonathan Leffler
@Jonathan: duly noted
kurosch
A: 

In Oracle you can do:

SELECT * FROM table
WHERE UPPER(REGEXP_REPLACE(NAME,'( ){2,}', ' ') = 'JOHN DOE';

No false positives like 'john mordoe' etc.

Robert Merkwürdigeliebe