How to spilt Fullname to First name, middlename and lastname in Query Builder? - sql

I have a table and there is a "name" field, but sometimes there are names that are too long, how do I just take the first name, middle name and last name (only 3 words)?
$student = DB::table('student')
->select('student.name')//Split to Firstname, Middlename&Lastname
->get();

I dont think eloquent can do this. You need to use php builtin functions
$fullname = explode(" ", $student);
$firstname = array_shift($split);
$lastname = implode(" ", $split);

Simpliest Way I think. Hope will help you
For me, it's a bad idea of splitting one word(fullname) into three, because what if, there are two words in his firstname, so the problem will exist as you are wishing only three words(first,middle,&lastname).
But if you really want to pursue, here's the code for that:
$student = DB::table('student')
->select(
'student.name',
DB::raw("SUBSTRING_INDEX(student.name, ' ', 1) AS Firstname"),
DB::raw("SUBSTRING_INDEX(SUBSTRING_INDEX(student.name, ' ', 2),' ',-1) AS Middlename"),
DB::raw("SUBSTRING_INDEX(SUBSTRING_INDEX(student.name, ' ', 3),' ',-1) AS Lastname")
)
->get();
I assume you use or it is space(' ') that joins three words (first,middle, & last name)
Note examples outputs:
1. John Ghost Pon
Firstname = "John", Middlename = "Ghost", Lastname = "Pon"
2. Marry Anne Smith Ingram
Firstname = "Marry", Middlename = "Anne", Lastname = "Smith"
SUBSTRING_INDEX Function returns a substring of a string before a specified number of delimiter occurs: More examples
Please let me know if still doesn't work.

Related

SQL query for User.first_name OR User.last_name OR both?

I'm programming a Rails app that allows a user to search for other users. Currently, a user can search first or last name, but not both.
I'm using:
#users = User.all.where("lower(first_name) LIKE :search OR lower(last_name) LIKE :search", search: "%#{parameter}%")
Given that the attributes are separate, how can I handle a search like "Harry Potter" with a space? I've looked around at ignoring spaces and then trying to separate the first and last, but they all seem quite complicated.
You can try concatenating firstname and lastname with ||:
User.where(
"(LOWER(firstname) || ' ' || LOWER(lastname)) LIKE :search",
search: '%HARRY potter%'
)
You can split the name to first_name and last_name then
User.where(
"lower(first_name) LIKE :first_name AND lower(last_name) LIKE :last_name",
first_name: "%#{first_name}%", last_name: "%#{last_name}%"
)

ActiveRecord (SQL) query multiple columns only if search string not empty

Using a PG database filled with registered voters.
Trying to set it up so I can search by first name, last name, zip or city. I want to be able to find all voters that match all of the entered params, but having trouble dealing with empty search fields.
where("zip LIKE ? OR city LIKE ? OR last_name LIKE ? OR first_name LIKE ?",
"#{params[:zip]}","#{params[:city]}","#{params[:last_name]}","#{params[:first_name]}")
Is there a better way to build it out so that it matches ALL entered parameters, but ignores empty string parameters? Right now if I enter a first and last name 'John Smith' I will get 'John Jones' and 'Jane Smith'.
This can do the trick:
attrs_name_to_search = %w( zip city last_name first_name )
fitlered_params = params.slice(*attrs_name_to_search).select { |_,v| v.present? }
sql_cond = filtered_params.map { |k,_| "#{k} LIKE :#{k}" }.join(' OR ')
YourModel.where(sql_cond, filtered_params)
But it should return all the records if no zip/city/last_name/first_name is given.

How to make SQL search query for firstname, lastname

If I have for example an model:
User :firstname :lastname
joseph smith
anna bauer
... ...
And an input field where you can search for an user. The different search queries could be:
searchquery1: smith joseph
searchquery2: joseph smith
searchquery3: joseph
searchquery4: smith
Which search query in SQL would be the best? Actually I could imagine this search query:
where 'firstname OR lastname LIKE ?', "%#{search}"
First try:
def self.search(search)
if search
select('CONCAT(vorname, " ", nachname) as full_name, *')
where ['vorname LIKE :s OR nachname LIKE :s OR full_name LIKE :s', :s => "%#{search}"]
else
scoped
end
end
error: SQLite3::SQLException: no such column: full_name
Second try:
def self.search(search)
if search
a = search.split
where('firstname OR lastname LIKE ?', a[1])
where('firstname OR lastname LIKE ?', a[2]) unless a[2].nil?
else
scoped
end
end
Problem: Finds nothing!
Yes, you have to search it on both first name and last name like this
select('(firstname || " " || lastname) as \'full_name\', *')
where ['firstname LIKE :s OR lastname LIKE :s OR full_name LIKE :s', :s => "%#{search}"]
but if the data is too big. You can use the full text search engines like Solr or thinkin sphinx
To make search on firstname, lastname and fullname;
Member.where ['first_name LIKE :s OR last_name LIKE :s OR CONCAT(first_name,last_name) LIKE :s', :s => "#{search.delete(' ')}"]
It works!
Yes, if you want search on lastname and firstname you must do :
User.where('firstname or lastname like ?', params[:search])
An another solution : https://github.com/ernie/squeel, https://github.com/ernie/squeel#predicates
User.where("(first_name || ' ' || last_name) like :q", :q => params[:search])

concatening rows in a rails style

Suppose I want to check if some string appears as name-surname in the concatenation of two rows name and surname of a table. How do I write valid this sql in a rails style ? And is these syntaxes correct ?
SELECT (name + '-'+ surname) FROM table1 where (name + '-'+ surname = string)
table.select(:name+'-'+:surname).where((:name+'-'+:surname) == string)
I am not sure if I am understanding your question correctly, but I think this is what you are wanting. For the following string variable,
string = "John - Doe"
you want to pull a record like this from the User table
id | name | sur_name
1 | John | Doe
If this is what you want, you can actually massage your string variable like this
parsed_string = string.split('-')
name = parsed_string[0].strip # strip to remove white spaces
sur_name = parse_string[1].strip
Then, you can run the following code to get what you want:
users = User.where(:name => name, :surname => sur_name)
Hope this answers your question.

in sqlalchemy can or_ look into two columns when more than one word is entered?

I have the following command that's kind of working as expected:
DBSession.query(Users).filter(or_(Users.first_name.contains(search_term),Users.last_name.contains(search_term))).all()
I searches both first and last name in my Users table, so I can find bob smith by searching either bob or smith, but I get no results when I search bob smith. This is obviously because bob is in the first_name column and not bob smith so it fails. But is there a way to do this kind of search within sqlalchemy?
I know worst I can create a column with the full name but I thought I'd ask just in case it was possible. I'm also tagging this as sql just in case its possible with raw sql then I will just try to igure out the sqlalchemy version based on the raw query.
The easiest way to achieve this is to use Hybrid Attributes extension:
from sqlalchemy.ext.hybrid import hybrid_property
class User(Base):
#...
first_name = Column(String, nullable=False)
last_name = Column(String, nullable=False)
#hybrid_property
def full_name(self):
return self.first_name + " " + self.last_name
#hybrid_property
def _full_name_last_first(self):
""" #note: used only for search [last, first]. """
return self.last_name + ", " + self.first_name
def test_search(search_term):
q = session.query(User)
q = q.filter(
or_(
User.first_name.contains(search_term),
User.last_name.contains(search_term),
User.full_name.contains(search_term),
User._full_name_last_first.contains(search_term),
),
)
q = q.order_by(User.id)
return q.all()
r1 = test_search('John Williams')
assert len(r1) == 1
r1 = test_search('Williams, Jo')
assert len(r1) == 1