Search Results Rails SQL - Searching for users - sql

I have a search field in my navigation bar where people can search for other users, like fb's friend search.
In my Users table i have first_name and last_name as columns and would like the search results to look through both tables. Right now I just have it working with the first name.
#usersfiltered = User.where("first_name LIKE?", "%#{params[:first_name]}%" )
Ideally, if there was an user named Bob Smith his name would come up if Bob, Smith, or Bob Smith was searched.
How would you go about adding to the SQL statement? I've tried a few things but keep getting errors. Thanks

You can use a symbol in your where method to pass in one value for multiple column like this:
#usersfiltered = User.where("first_name LIKE :search_name or last_name LIKE :search_name",
search_name: "%#{params[:search_word]}%" )
Update:
To search for first_name and last_name combined, you could concatenate the two fields and add another OR condition.
The problem here is different databases have their own concatenation style. Following are for MySQL and Postgres.
MySQL:
#usersfiltered = User.where("first_name LIKE :search_name or last_name LIKE :search_name or concat(first_name, ' ', last_name) like :search_name",
search_name: "%#{params[:search_word].squish}%" )
Postgres:
#usersfiltered = User.where("first_name LIKE :search_name or last_name LIKE :search_name or (first_name || ' ' || last_name) like :search_name",
search_name: "%#{params[:search_word].squish}%" )
I also added the Ruby string function squish, to take care of extra spaces.

#usersfiltered = User.where("first_name LIKE ? OR last_name LIKE ?", "%#{params[:first_name]}%", "%#{params[:last_name]}%")
However, if you have just one field that the user is typing into and you want to use it to search multiple names, I would think you'd want to name it something else besides "first_name" and use the approach described in the other answer.

Related

Using Contains how to search for more than one value

Here is what I am trying to do:
select * from Person where CONTAINS((fName,sName),'John AND Doe')
So I am trying to search for John Doe but I get that I cannot use AND here (just showing my chain of thought) so how can I search for John in the fName and Doe in the sName ? But I don't want to use "Contains" twice like this:
SELECT * FROM Person
WHERE CONTAINS((fName), 'John')
AND CONTAINS((sName), 'Doe');
Since we can have
(fName,sName)
but I cannot use
'John','Doe'/'John' AND 'Doe'
Your statement
SELECT * FROM Person
WHERE CONTAINS((fName), 'John')
AND CONTAINS((sName), 'Doe');
can't compile because CONTAINS returns a number, not a boolean.
It shall respond,on oracle, with this kind of error
ORA-00920: opérateur relationnel non valide
00920. 00000 - "invalid relational operator"
(the relational operator error's cause is not the AND's existence, it's because you try to AND two numbers)
What do you intend to do? If you want to select the line in the person table whose fName columns contains the substring John and whose sName column contains the substring Doe, you may use the like operator, which uses % as a wildcard.
SELECT * FROM Person
WHERE fName LIKE '%John%'
and sName LIKE '%Doe%'
I don't practice much the CONTAINS method, but if you desire to use it, according to documentation, you should use something like
SELECT * FROM Person
WHERE CONTAINS(fName, 'John') > 0
and CONTAINS(sName,'Doe') > 0
If you really don't want to use the AND operator (for whatever obscure reason like proving a sql injection filter is bad), you can use this trick : compare a concatenation of the 2 columns and the like operator like so
SELECT * FROM Person
WHERE fName || sName like '%John%Doe%';
but this last trick will also match the line where fname is John Doe and sName is Jean-Michel :)
This should work:
SELECT * FROM dbo.Person
WHERE CONTAINS((fName), 'John')
AND CONTAINS((sName), 'Doe');
But in your case you dont want to use 2 contains so:
Alternatively, you could add a new computed column with a full text index on it.
Add a column like this:
computedCol AS fName+ ' ' + sName
And create the full text index:
CREATE FULLTEXT INDEX ON Person(computedCol LANGUAGE 1033)
KEY INDEX pk_Person_yourPrimaryKeyName
Then you can do this:
SELECT * FROM dbo.Person
WHERE CONTAINS(*, 'John AND Doe')
Hope it works.

How can i compose two columns to apply a filter?

I have a table with two columns: first_name and last_name. At the application the user sees the full name (eg first + last names).
Example:
first_name last_name
bat man
Barack Obama
In the application if the user searches for "bat man" he got no result.
So, how can I filter using both columns?
My current sql:
select *
from people
where first_name ilike 'bat man'
or last_name ilike 'bat man'
You're looking for the string concatenation operator, ||:
SELECT *
FROM people
WHERE (first_name || ' ' || last_name) ILIKE 'bat man'
See §9.4 "String Functions and Operators" in PostgreSQL 9.4.4 Documentation.

SQL checking the last letter in string / AKA LIKE strange behaviour

I know it was already answered but it doesn't work for me.
So quick introduce:
I have table called swimmers. I'll insert new record to it which fulfils all columns:
INSERT INTO swimmers(id, first_name, last_name, age, gender)
VALUES(9,'Maria','Spolsky',34,'Female');
Now I want to find records in swimmers table which first_name DOES NOT end with letter a and where gender is Female
So I wrote SQL query:
SELECT first_name, last_name
FROM swimmers
WHERE first_name NOT LIKE '%a' AND gender = 'Female'
But it does return Maria which we just added. It basically returns every female
I'm using ORACLE iSQL plus.
EDIT:
I tried to use substr(first_name, -1) = 'a' but it turned out that -1 is empty, because I use varchar(20) and names are usually smaller than 20 characters
EDIT2:
I tried to find issue in data type. I used char(20) for first_name.
I changed it into varchar2(20):
ALTER TABLE swimmers
MODIFY first_name varchar2(20);
but didn't solve the issue
EDIT 3:
Changing NOT LIKE to WHERE first_name LIKE '%a' returns no rows. I believe issues lies inside data type and empty spaces from the end of the first_name to the end of reserved space for string (names has ~10 characters and I use `varchar2(20))
Appearantly oracles is adding spaces behind the name and that's why '%a' doesn't work, either change your column definition to a varchar (so oracle doesn't add the extra spaces) or trim the spaces out of your name like this:
SELECT first_name, last_name
FROM swimmers
WHERE NOT trim(first_name) LIKE '%a' AND gender = 'Female';

SQL prompt to enter a letter that the last name starts with

The whole question is:
Rewrite the query so that the user is prompted to
enter a letter that the last name starts with. For example, if the user enters “H" (capitalized) when prompted for a letter, then the output should show all employees whose last name starts with the letter “H.”
SELECT last_name
FROM employees
WHERE last_name like '%' = &Start_Letter
This wont work :(
This query should work:
SELECT last_name FROM employees WHERE last_name like '&Start_Letter%';
I have tested it in Oracle11g.
SELECT last_name FROM employees WHERE last_name like &Start_Letter + '%';
Depending on the requirements of your particular application, a more efficient solution might be to create a function based index:
CREATE INDEX emp_start_letter_idx
ON employees ( substr( last_name, 1, 1 ) );
Then your query would be:
SELECT last_name
FROM employees
WHERE substr(last_name, 1, 1) = '&Start_Letter';
Likewise, depending on your requirements, this may be a lot of unnecessary fuss!

why can't i use like and equal operators together in my search query

what i'm trying to do it's simple search by three columns: firstname, lastname and email
in my case i need that two first colums (firstname and lastname) will be searchable by like operator and the last one (email) by equal operator
but im getting error that does not explain what should i do:
in plain sql it should be something like this:
Select *
From Member
Where FirstName like '%value%' Or LastName like '%value%' Or Email='value'
but what im doing wrong?
You can try with
.Where(Restrictions.Disjunction()
.Add(Restrictions.On(x => x.FirstName).IsLike(keyWord))
.Add(Restrictions.On(x => x.LastName).IsLike(keyWord))
.Add(Restrictions.On(x => x.FirstName).IsLike(keyWord))
.Add(Restrictions.Eq(x.Email,keyWord))
)
I hope it's helpful