Mysql search, order according to priority - mysql

I decided that I wanted a search field on my website, the thing is I don't really have any knowledge about search algorithms. The search box works like you can enter any number of names(username, firstname, lastname) or emails separating each by a space. So I came up with the following using codeigniter's active record class (it's very simple):
$emails = FALSE;
$names = FALSE;
foreach($search_array as $value){
if(valid_email($value)){
$emails[] = $value;
} else{
$names[] = $value;
}
}
if($emails){
$this->db->where_in('email', $emails);
if($names){
$this->db->or_where_in('username', $names);
$this->db->or_where_in('firstname', $names);
$this->db->or_where_in('lastname', $names);
}
} else{
if($names){
$this->db->where_in('username', $names);
$this->db->or_where_in('firstname', $names);
$this->db->or_where_in('lastname', $names);
}
}
$this->db->select('id, username, firstname, lastname');
$query = $this->db->get('users');
if($query->num_rows() > 0){
return $query->result();
}
return FALSE;
What this code does is running a bunch of where statements and then simply sending it all back.
Perhaps I could clean up the if-statements and how the email works, but that's not the point. This code works perfectly (at least with a very small database :P) but I want it to do more:
Right now you need to enter the correct name or email to get any good result. If your almost right it would be nice to get some suggestions but that I probably can figure that out by myself doing some LIKE.
I want to sort the whole result array, and here is where I'm stumbling. Since both the email and the username is unique I want a search to display using the following priorities:
Email
Username
Firstname + Lastname
Firstname
Lastname
Well for the time being I don't really care about for example Email+username+firstname+lastname since I believe that would be way to overwhelming :P
I did found this topic Search query, 'order by' priority but since I don't know which is what in my search it didn't really help me but perhaps I could use something similar?
Anyway you guys know a way to solve the priority problem? Have I perhaps missed some major functions that could help? And what will happen when my database goes big? ;)
Thanks for all help!

You can do:
ORDER BY email != 'value',
username != 'value',
firstname != 'value' AND lastname != 'value',
firstname != 'value',
lastname != 'value'
If the expression is false (meaning they are the same) then it's equal to 0 and will sort higher than an expression that is true (meaning they are different) which equals 1 and sorts after a 0.
If you find the != confusing then this is the same thing:
ORDER BY email = 'value' DESC,
username = 'value' DESC,
firstname = 'value' AND lastname = 'value' DESC,
firstname = 'value' DESC,
lastname = 'value' DESC

Related

Laravel Join Query returning empty column

I have a member table with some entries. Each member can create a user account in laravel's users table.
They each have a field called "person_id" and that's how the connection is made.
I have a search that returns a list with all of them. I have a checkbox "Search only registered" that means it returns only members that have users account, otherwise if the check doesn't check, return a mix with all of them.
The thing is, no matter if the checkbox is checked or not, the person_id must be pulled for each one.
if($reg == 'on') {
$Members = $Members->rightJoin('users', 'users.person_id', '=', 'members.person_id');
}
else {
$Members = $Members->leftJoin('users', 'users.person_id', '=', 'members.person_id');
}
I tried with leftJoin but person_id comes empty
at first look if you are using Eloquent i can tell you are missing the "->get();" at the end of each query.
Hope this helps.
Use relation in member model:
public function user()
{
return $this->belongsTo('App\User', 'person_id', 'person_id' );
}
public function getMemberWithUser()
{
return $this->select('*')->with('user')->get()->toArray();
}
and use (new Member)->getMemberWithUser(); in controller. That will return you member detail with user.
Neverming guys I found it out.
Most members don't have yet a user account, only 2. And the select wasn't specifying which table to take the person_id from. And with most members missing an user account, it was trying to get it from users.
I did this:
$Participants = Member::select(
'members.first_name',
'members.last_name',
'members.person_id',
'members.email'
);

Codeigniter, Active Record doesn't accept WEEK parameter

It seems that Active Record (Codeigniter) doesn't accept the WEEK parameter and I don't understand why?!
Whern i remove '3', my query works properly!
$this->db->select('WEEK(insere_le,3) AS semaine, COUNT(*) AS nombre')
->from($this->table_name)
->where(array(
'type_anomalie' => "Dérogation",
'YEAR(insere_le)' => $year
))
->group_by('WEEK(insere_le,3)')
->get()
->result_array();
This query, shows the following string when I execute it:
SELECT WEEK(insere_le, `3)` AS semaine, COUNT(*) AS nombre FROM (`aero_anomalie_montage`) WHERE `type_anomalie` = 'Dérogation' AND YEAR(insere_le) = '2014' GROUP BY WEEK(insere_le, `3)`
As you can see it adds an apostrophe before the number 3 and after the parenthesis )
It looks a little confused by your syntax. Why not put them in two different selects (if that's possible...)?
I don't know if this will help, but I found this, it will prevent it from adding the backticks altogether.
$this->db->select() accepts an optional second parameter. If you set
it to FALSE, CodeIgniter will not try to protect your field or table
names with backticks. This is useful if you need a compound select
statement.
http://ellislab.com/codeigniter/user-guide/database/active_record.html
hmm, if you look at active rec class (system/core/database/DB_active_rec.php) you will find this in function select() :
if (is_string($select))
{
$select = explode(',', $select);
}
so what you're select is doing is actually exploding your string into an array like this:
array(
WEEK(insere_le,
3) AS semaine,
COUNT(*) AS nombre
);
and then processing this.
This looks like an oversight from the developers of the active record class, and probably won't be solved by not escaping the values...
On the other hand, it actually checks its a string prior to the above.. so could try this:
$this->db->select(array('WEEK(insere_le,3) AS semaine', 'COUNT(*) AS nombre'))...
and the same with group_by(array('WEEK(insere_le,3)'))...
so end result would be:
$this->db->select(array('WEEK(insere_le,3) AS semaine', 'COUNT(*) AS nombre'))
->from($this->table_name)
->where(array(
'type_anomalie' => "Dérogation",
'YEAR(insere_le)' => $year
))
->group_by(array('WEEK(insere_le,3)'))
->get()
->result_array();
you tried this?:
$this->db->select("WEEK(insere_le,3) AS semaine, COUNT(*) AS nombre", FALSE);

Zend Framework - join query

I build a function
public function getBannedByLogin($commentId)
{
$sql = $this->getDbAdapter()->select()
->from(array('comments' => 'comments'), array())
->join(array('users' => 'qengine_users'),
'comments.bannedBy = users.userId',
array())
->where('commentId = ?', $commentId)
;
$row = $this->fetchRow($sql);
return $row['login'];
}
And there are problems, that does'nt work! :D
Let's I explain you. Column 'bannedBy' from comments returns id of user, who give a ban. I need to join this with table users to load a login field. Where i have mistakes?
I assume the code works in the sense of not throwing an exception. If so, your code is OK, you just specifically tell Zend_Db not to select any columns.
public function getBannedByLogin($commentId)
{
$sql = $this->getDbAdapter()->select()
->from(array('comments' => 'comments'))
->join(array('users' => 'qengine_users'),
'comments.bannedBy = users.userId')
->where('commentId = ?', $commentId)
;
$row = $this->fetchRow($sql);
return $row['login'];
}
The last argument to from() and join() functions is an array of columns you wish to select. If you pass in an empty array, no columns are selected. No argument = select everything. You can, of course, specify only the columns you need too.

Codeigniter mysql where not equal to query

Mysql codeigniter query is not working properly.
Suppose if mysql table looks like this:
user_id|user_name
1|john
2|alex
3|sam
Here user_name is unique
The following query should return false if user_name=john and user_id=1 and true if say user_name=john and user_id=2.
$this->db->get_where('user', array('user_name' => $name,'user_id !=' => $userid));
But it returns true in the case user_name=john and user_id=1.
Can anyone suggest me an alternative way of querying not equal to.
print($this->db->last_query()) gives:
SELECT * FROM (user) WHERE user_name = 'john' AND user_id != '1'
Why dont you use simple $this->db->query('your query');
Simply try this, Add the desired condition in the where function.
$this -> db -> where('invitee_phone !=', $user_phone);
You can go follwoing way too. It work for me
$total = 5;
$CI = get_instance();
$CI->load->database();
$CI->db->order_by('id','asc');
$topusers = $CI->db->get_where('users',array('user_type != 1 && `status` =' => 1),$total,0);
echo $CI ->db ->last_query();
die;
and if still not work for you can go with #rohit suggest: $this->db->query('your query');
Type 1:
Using ->where("column_name !=",$columnname) is fine for one column.
But if you want to check multi columns, you have to form an array inside where clause.
Like this
$whereArray = array(
"employee_name" => $name,
"employee_id !=" => $id,
);
$this->db->select('*')->from('employee')->where($whereArray);
Type 2:
We can just write exactly what we want inside where.
Like
$thi->db->where(("employee_id =1 AND employee name != 'Gopi') OR designation_name='leader#gopis clan'");
Type 2 is good for working with combining queries, i mean paranthesis "()"
you can follow this code:
$query = $this->db->select('*')->from('employee')->where('user_name', $name)->where('user_id !=', $userid)->get();
$last_query = $this->db->last_query();
$result = $query->result_array();
if you pass $name = 'john' and $userid = '1' then it return empty array.
The problem with using $this->db->query('your query'); is that it is not portable. One of the most important reasons to embrace the query builder methods is so that no matter what database driver you use, CodeIgniter ensures that the syntax is appropriate.
If a bit of discussion was possible, I'd probably like to hear why you need composite primary identifiers in your table and I'd like to see what your table schema looks like. However, I think the time for discussion has long passed.
Effectively, you want to return a boolean result stating the availability of the combination of the username AND the id -- if one is matched, but not both, then true (available).
To achieve this, you will want to search the table for an exact matching row with both qualifying conditions, count the rows, convert that integer to a boolean, then return the opposite value (the syntax is simpler than the explanation).
Consider this clean, direct, and portable one-liner.
return !$this->db->where(['user_name' => $name,'user_id' => $userid])->count_all_results('user');
this will return false if the count is > 0 and true if the count is 0.

"No result was found for query although at least one row was expected." Query should display records though in Symfony

I'm trying to retrieve content using two items in the URL. Here is the php/symfony code that should do it:
$em = $this->getDoctrine()->getEntityManager();
$repository = $this->getDoctrine()
->getRepository('ShoutMainBundle:Content');
$query = $repository->createQueryBuilder('p')
->where('p.slug > :slug')
->andWhere('p.subtocontentid > :parent')
->setParameters(array(
'slug' => $slug,
'parent' => $page
))
->getQuery();
$content = $query->getSingleResult();
However, when this code is executed it returns the following error:
No result was found for query although at least one row was expected.
I have done some tests, and the data held in the $slug and $page variables hold the correct information. I have also tested the MySQL query and the query brings up the desired result, which confuses me further.
Have I missed something?
As it was answered here
You are getting this error because you are using the
getSingleResult() method. it generates an Exception if it can't find
even a single result. you can use the getOneOrNullResult() instead
to get a NULL if there isn't any result from the query.
Query#getSingleResult(): Retrieves a single object. If the result
contains more than one object, an NonUniqueResultException is thrown.
If the result contains no objects, an NoResultException is thrown. The
pure/mixed distinction does not apply.
No result was found for query although at least one row was expected.
Another reason could be:
You did this
$query = $this->getEntityManager()
->createQuery('
SELECT u FROM MyBundle:User u
WHERE u.email = :email')
->setParameter('email', $email);
return $query->getSingleResult();
Instead of this
$query = $this->getEntityManager()
->createQuery('
SELECT u FROM MyBundle:User u
WHERE u.email = :email')
->setParameter('email', $email);
$query->setMaxResults(1);
return $query->getResult();
Don't you want to use "=" instead of ">" ?
If you've got this message because used
$content = $query->getSingleResult();
you can just replace it with the row below
$content = $query->getOneOrNullResult(AbstractQuery::HYDRATE_SINGLE_SCALAR) ?? 0;