I'm producing a query like the following using ActiveRecord
SELECT * FROM (`foods`) WHERE `type` = 'fruits' AND
`tags` LIKE '%green%' OR `tags` LIKE '%blue%' OR `tags` LIKE '%red%'
The number of tags and values is unknown. Arrays are created dynamically. Below I added a possible array.
$tags = array (
'0' => 'green'.
'1' => 'blue',
'2' => 'red'
);
Having an array of tags, I use the following loop to create the query I posted on top.
$this->db->where('type', $type); //var type is retrieved from input value
foreach($tags as $tag):
$this->db->or_like('tags', $tag);
endforeach;
The issue: I need to add parentheses around the LIKE clauses like below:
SELECT * FROM (`foods`) WHERE `type` = 'fruits' AND
(`tags` LIKE '%green%' OR `tags` LIKE '%blue%' OR `tags` LIKE '%red%')
I know how to accomplish this if the content within the parentheses was static but the foreach loop throws me off..
From the CI wiki:
The codeignighter ActiveRecord feature
allows you to create SQL queries
relatively simply and
database-independant, however there
isno specific support for including
parenthesis in an SQL query.
For example when you want a where statement to come out simmilarly to the folowing:
WHERE (field1 = value || field2 = value) AND (field3 = value2 || field4 = value2)
This can be worked around by feeding a string to the CI->db->where() function, in this case you will want to specifically escape your values.
See the following example:
$value=$this->db->escape($value);
$value2=$this->db->escape($value2);
$this->db->from('sometable');
$this->db->where("($field = $value || $field2 = $value)");
$this->db->where("($field3 = $value2 || $field4 = $value2)");
$this->db->get();
A simmilar workaround can be used for LIKE clauses:
$this->db->where("($field LIKE '%$value%' || $field2 LIKE '%$value%')");
$this->db->where("($field3 LIKE '%$value2%' || $field4 LIKE '%$value2%')");
In the CI 3.0-dev you can add groups in query:
$this->db->select('id, title')
->group_start()
->or_like([ 'title' => $s, 'id' => $s ])
->group_end()
->where([ 'b_del' => 0 ]);
Produces:
SELECT `id`, `title`, `venda1`
FROM `itens`
WHERE
(
`title` LIKE '%a%' ESCAPE '!'
OR `id` LIKE '%a%' ESCAPE '!'
)
AND `b_del` =0
One of best feature to save your query when you applying multiple where or_where clauses.
$this->db->group_start();
$this->db->where();
$this->db->or_where();
$this->db->group_end();
Happy Coding. :)
Going off of The Silencer's solution, I wrote a tiny function to help build like conditions
function make_like_conditions (array $fields, $query) {
$likes = array();
foreach ($fields as $field) {
$likes[] = "$field LIKE '%$query%'";
}
return '('.implode(' || ', $likes).')';
}
You'd use it like this:
$search_fields = array(
'field_1',
'field_2',
'field_3',
);
$query = "banana"
$like_conditions = make_like_conditions($search_fields, $query);
$this->db->from('sometable')
->where('field_0', 'foo')
->where($like_conditions)
->get()
Just adding my successful solution:
$this->db->where("(table.field = $variable OR table.field IS NULL)");
use codeigniter 3
$this->db->select('*');
$this->db->from($this->MasterMember);
$this->db->group_start();
$this->db->where($this->IDCardStatus, '1');
$this->db->or_where($this->IDCardStatus, '2');
$this->db->group_end();
if ($searchKey1 != null) {
$this->db->group_start();
$this->db->like($this->MemberID, $searchKey1);
$this->db->or_like($this->FirstName, $searchKey2);
$this->db->or_like($this->LastName, $searchKey3);
$this->db->group_end();
}
$this->db->limit($limit, $offset);
$data = $this->db->get();
this is my native query
SELECT
*
FROM
`Member`
WHERE ( `Member`.`IDCardStatus` = '1' OR `Member`.`IDCardStatus` = '2' )
AND ( `Member`.`MemberID` LIKE '%some_key%' ESCAPE '!' OR `Member`.`FirstName` LIKE '%some_key%' ESCAPE '!' OR `Member`.`LastName` LIKE '%some_key%' ESCAPE '!' )
LIMIT 10
Update for codeigniter 4:
$builder->select('*')->from('my_table')
->groupStart()
->where('a', 'a')
->orGroupStart()
->where('b', 'b')
->where('c', 'c')
->groupEnd()
->groupEnd()
->where('d', 'd')
->get();
// Generates:
// SELECT * FROM (`my_table`) WHERE ( `a` = 'a' OR ( `b` = 'b' AND `c` = 'c' ) ) AND `d` = 'd'
from official docs on: https://codeigniter.com/user_guide/database/query_builder.html#query-grouping
$likes = array (
'0' => 'green'.
'1' => 'blue',
'2' => 'red'
);
$where_like = "(";
$or_counter = 1;
foreach($likes as $like_key => $like_val):
$or_content = ($or_counter > 1) ?'OR': '';
$newlikeval = $this->db->escape_like_str($like_val);
$where_like .= $or_content." `$like_key` LIKE '%$newlikeval%' ";
$or_counter++;
endforeach;
$where_like .= ")";
$this->db->where($where_like);
You can't add parentheses in ActiveRecord, but maybe WHERE IN is what you're looking for?
$names = array('Frank', 'Todd', 'James');
$this->db->where_in('username', $names);
// Produces: WHERE username IN ('Frank', 'Todd', 'James')
Related
I have a query like this:
SELECT
foo.bar
FROM
foo
WHERE
foo.bang = 0
AND (
CASE
WHEN ? = 2 THEN foo.baz IS NOT NULL
WHEN ? = 1 THEN foo.baz IS NULL
ELSE ? NOT IN (1, 2)
END
)
AND (
(? = 0)
OR
(foo.bang = ?)
)
where the placeholders (?) are used as inputs for filter parameters:
my $query = $aboveQuery;
my ( $results ) = $dbh->DBI::db::selectall_arrayref(
$query,
{ Slice => {} },
$bazFilter,
$bazFilter,
$bazFilter,
$bangFilter,
$bangFilter,
);
This works, but it's not very reader-friendly.
MySQL supports # variables, which would increase readability:
SET #bazFilter = ?; -- passed in via selectall_arrayref or execute;
SET #bangFilter = ?;
SELECT
foo.bar
FROM
foo
WHERE
foo.bang = 0
AND (
CASE
WHEN #bazFilter = 2 THEN foo.baz IS NOT NULL
WHEN #bazFilter = 1 THEN foo.baz IS NULL
ELSE #bazFilter NOT IN (1, 2)
END
)
AND (
(#bangFilter = 0)
OR
(foo.bang = #bangFilter)
);
I'd like to do something like this instead:
my $query = $aboveAtVariablizedQuery;
my ( $results ) = $dbh->DBI::db::selectall_arrayref(
$query,
{ Slice => {} },
$bazFilter,
$bangFilter,
);
but MyISAM apparently won't do multiple statements in a single query.
My google-fu is failing me.
Is there a good way to mix-and-match the #variables with the placeholders?
Do each statement separately, using execute not one of the fetch methods.
# variables are local to the connection, so there is no problem with contamination between threads.
If the goal is to have a single query with no repeated substitutions, then consider:
SELECT foo.bar
FROM ( SELECT baz = ?, bang = ? ) AS init
JOIN foo
WHERE foo.bang = 0
AND (
CASE
WHEN init.baz = 2 THEN foo.baz IS NOT NULL
WHEN init.baz = 1 THEN foo.baz IS NULL
ELSE init.baz NOT IN (1, 2)
END
)
AND (
(init.bang = 0)
OR
(foo.bang = init.bang)
);
I want codeigniter search to be match with any one word to column.
Example: Let's Say Search Query is "Fashion Outlet for Mens", Now in table column title is "Fashion Outlet" only so i want search input to be split word by word and match column.
Any Help Please
public function search($query)
{
$q = $this->db->from('tablename')
->like('title',$query)
->get();
return $q->result();
}
Updated Question
public function search_query($query,$limit,$offset)
{
$keywords = explode(' ', $query);
foreach ($keywords as $keyword)
{
$keyword = trim($keyword);
$this->db->or_where("`title` LIKE '%$keyword%'");
$this->db->join('table2', 'tablename.id = table2.id');
$this->db->limit( $limit , $offset );
$this->db->order_by('updated_on','desc');
}
$this->db->get('tablename');
return $this->db->result();
}
Error Got
Not unique table/alias: 'table2'
SELECT * FROM `tablename` JOIN `table2` ON `tablename`.`id` = `table2`.`id` JOIN `table2` ON `tablename`.`id` = `table2`.`id` WHERE `title` LIKE '%fashion%' OR `title` LIKE '%outlet%' ORDER BY `updated_on` DESC, `updated_on` DESC LIMIT 50
Please find the Updated Answer for Order By Keyword Priority.
$keywords = explode(' ', $query);
$this->db->select('*');
$this->db->from('tablename');
$this->db->join('table2', 'tablename.id = table2.id','left');
$orderbyQry = "CASE ";
foreach ($keywords as $key => $keyword)
{
$orderbyQry.="WHEN tablename.title LIKE '%$keyword%' THEN $key ";
$keyword = trim($keyword);
$this->db->or_where("tablename.title LIKE '%$keyword%'");
}
$orderbyQry.=" ELSE 100 END ";
$this->db->limit( $limit , $offset );
$this->db->order_by($orderbyQry,'asc');
$this->db->get();
return $this->db->result();
Please join the table only once, and put the limit and order_by clause out of the loop.
public function search_query($query, $limit, $offset) {
$keywords = explode(' ', $query);
$this->db->select('*');
$this->db->join('table2', 'tablename.id = table2.id');
foreach ($keywords as $keyword)
{
$keyword = trim($keyword);
$this->db->or_where("`title` LIKE '%$keyword%'");
}
$this->db->limit( $limit , $offset );
$this->db->order_by('updated_on','desc');
$this->db->get('tablename');
return $this->db->result();
}
Codeigniter Active records query gives me error. how to put SOUNDS LIKE into where clause.
function _search($type, $q, $qes, $sort = null, $start = 0) {
$type = strtolower($type);
$q = strtolower($q);
$this->db->select("*");
$this->db->from("books");
$this->db->where("SOUNDEX(name) IN({$q})");
foreach($qes as $k){
$this->db->or_where("name SOUNDS LIKE '$k'");
}
foreach($qes as $k){
$this->db->or_where("name LIKE '%$k%'");
}
$this->db->where("status", 1);
if ($type != NULL) {
$this->db->where("LOWER(type)", $type);
}
//$this->db->like("LOWER(name)", $q);
$this->db->limit(BWK_MAX_BOOK_SIZE, $start);
switch ($sort) {
case 1:
break;
case 2:
$this->db->order_by("sellingPrice", "ASC");
break;
case 3:
$this->db->order_by("sellingPrice", "DESC");
break;
case 4:
$this->db->order_by("created", "DESC");
break;
}
this gives me query when i echo query. i am searching for technologi i need to get technology technologies etc.
SELECT * FROM `books` WHERE SOUNDEX(name) IN('t254') OR `name` `SOUNDS` LIKE 'technolog' OR `name` LIKE '%technologi%' AND `status` = 1 AND LOWER(type) = 'school' LIMIT 50
getting error
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`SOUNDS` LIKE 'technolog' OR `name` LIKE '%technolog%' AND `status` = 1 AND LOWE' at line 4
every thing works fine but when i put SOUNDS LIKE it gives me error.
its probably the best to group things here
you can try the following
$this->db
->select('*')
->from('books')
->where_in('SOUNDEX(name)', $q, NULL);
if (is_array($qes) && count($qes) > 0)
{
$this->db->group_start();
foreach($qes AS $k)
{
$this->db->or_group_start();
$this->db
->where('name SOUNDS LIKE '.$this->db->escape($k), NULL, false)
->or_like('name', $k);
$this->db->group_end();
}
$this->db->group_end();
}
if (!is_null($type))
{
$this->db->where('LOWER(type)', $type);
}
switch ($sort) {
case 1:
break;
case 2:
$this->db->order_by("sellingPrice", "ASC");
break;
case 3:
$this->db->order_by("sellingPrice", "DESC");
break;
case 4:
$this->db->order_by("created", "DESC");
break;
}
echo $this->db
->where('status',1)
->limit(BWK_MAX_BOOK_SIZE, $start)
->get_compiled_select();
this would produce a statement like
SELECT *
FROM `books`
WHERE SOUNDEX(name) IN('t254') AND
(
(
name SOUNDS LIKE 'technologi' OR
`name` LIKE '%technologi%' ESCAPE '!'
)
OR
(
name SOUNDS LIKE 'whatever' OR
`name` LIKE '%whatever%' ESCAPE '!'
)
)
AND `status` = 1
AND LOWER(type) = 'school'
LIMIT 50
From : DB_query_builder.php, what one can see is 3rd argument decides whether to escape or not.
public function or_where($key, $value = NULL, $escape = NULL){
}
So just tell that not to escape it
$this->db->or_where("name SOUNDS LIKE '$k'", NULL, FALSE);
Could you use the HAVING clause with your ORDER BY and your LIKE?
HAVING clause:
https://www.w3schools.com/sql/sql_having.asp
I want my query like this:
SELECT tbl_bids. * , tbl_department.vDeptName, tbl_user.vFirst
FROM tbl_bids
LEFT JOIN tbl_bids_department ON tbl_bids_department.iBidID = tbl_bids.iBidID
LEFT JOIN tbl_department ON tbl_department.iDepartmentID = tbl_bids_department.iDepartmentID
LEFT JOIN tbl_user ON tbl_user.iUserID = tbl_bids.iUserID
WHERE tbl_user.iUserID = '1' // with parantheses in where clause
AND (
tbl_department.vDeptName = 'PHP'
OR tbl_department.vDeptName = 'android'
)
GROUP BY tbl_bids.iBidID
ORDER BY iBidID DESC
LIMIT 0 , 30
But i can't find the way to get parantheses in my query,there are mutiple condition and loop will be there to make where clause..
here is my code
$select = $this->tableGateway->getSql()->select();
$select->columns(array('*'))
->join('tbl_bids_department', 'tbl_bids_department.iBidID = tbl_bids.iBidID', array(),"LEFT")
->join('tbl_department', 'tbl_department.iDepartmentID = tbl_bids_department.iDepartmentID',array(tbl_department.vDeptName),"LEFT")
->join('tbl_user', 'tbl_user.iUserID = tbl_bids.iUserID',array(tbl_user),"LEFT")
->group('tbl_bids.iBidID');
$where = new \Zend\Db\Sql\Where();
$where->equalTo( 'tbl_bids.eDeleted', '0' );
$sWhere = new \Zend\Db\Sql\Where();
for ( $i=0 ; $i<count($aColumns) ; $i++ )
{
if (isset($data['sSearch_'.$i]) && $data['sSearch_'.$i] != "")
{
if($aColumns[$i] == 'vDeptName'){
$allDept = explode(',', $data['sSearch_'.$i]);
foreach ($allDept as $key => $value) {
if($key == 0)
$sWhere->AND->equalTo("tbl_department.vDeptName", $value);
else
$sWhere->OR->equalTo("tbl_department.vDeptName", $value);
}
}elseif($aColumns[$i] == 'vFirst')
$sWhere->AND->equalTo("tbl_user.iUserID",$data['sSearch_'.$i]);
else
$sWhere->AND->like("tbl_bids.".$aColumns[$i], "%" . $data['sSearch_'.$i] . "%");
$select->where($sWhere); // here my where clause is create
}
}
//var_dump($select->getSqlString());
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
I have others many fields to pass through where which also have same problem of paratheses
if there is no any condition i can use nest() and unnest() predicate , but it will show me that string is not nested error,
So pls help me to find the solution.
Pls attach example with solution.
here is a short example
$where = new Sql\Where();
$where->equalTo('col',thirdVal')
->NEST //start braket
->equalTo('col','someVal')
->OR
->equalTo('col','secondVal')
->UNNEST //close bracet
hope this will help
I am using the following code to select from a MySQL database with a Code Igniter webapp:
$query = $this->db->get_where('mytable',array('id'=>10));
This works great! But I want to write the following MySQL statement using the CI library?
SELECT * FROM `mytable` WHERE `id`='10' OR `field`='value'
Any ideas?
Thanks!
$where = "name='Joe' AND status='boss' OR status='active'";
$this->db->where($where);
You can use or_where() for that - example from the CI docs:
$this->db->where('name !=', $name);
$this->db->or_where('id >', $id);
// Produces: WHERE name != 'Joe' OR id > 50
You can use this :
$this->db->select('*');
$this->db->from('mytable');
$this->db->where(name,'Joe');
$bind = array('boss', 'active');
$this->db->where_in('status', $bind);
Active record method or_where is to be used:
$this->db->select("*")
->from("table_name")
->where("first", $first)
->or_where("second", $second);
$where = "name='Joe' AND status='boss' OR status='active'";
$this->db->where($where);
Though I am 3/4 of a month late, you still execute the following after your where clauses are defined... $this->db->get("tbl_name");
What worked for me :
$where = '';
/* $this->db->like('ust.title',$query_data['search'])
->or_like('usr.f_name',$query_data['search'])
->or_like('usr.l_name',$query_data['search']);*/
$where .= "(ust.title like '%".$query_data['search']."%'";
$where .= " or usr.f_name like '%".$query_data['search']."%'";
$where .= "or usr.l_name like '%".$query_data['search']."%')";
$this->db->where($where);
$datas = $this->db->join(TBL_USERS.' AS usr','ust.user_id=usr.id')
->where_in('ust.id', $blog_list)
->select('ust.*,usr.f_name as f_name,usr.email as email,usr.avatar as avatar, usr.sex as sex')
->get_where(TBL_GURU_BLOG.' AS ust',[
'ust.deleted_at' => NULL,
'ust.status' => 1,
]);
I have to do this to create a query like this :
SELECT `ust`.*, `usr`.`f_name` as `f_name`, `usr`.`email` as `email`, `usr`.`avatar` as `avatar`, `usr`.`sex` as `sex` FROM `blog` AS `ust` JOIN `users` AS `usr` ON `ust`.`user_id`=`usr`.`id` WHERE (`ust`.`title` LIKE '%mer%' ESCAPE '!' OR `usr`.`f_name` LIKE '%lok%' ESCAPE '!' OR `usr`.`l_name` LIKE '%mer%' ESCAPE '!') AND `ust`.`id` IN('36', '37', '38') AND `ust`.`deleted_at` IS NULL AND `ust`.`status` = 1 ;