CakePHP 3.6 Query Builder complex OR conditions issue - cakephp-3.0

I am trying to build a query using query builder with complex nested AND and OR conditions. Here is what I have written so far.
$cond_arr = array();
$cond_arr['VehicleBrandModels.status'] = 1;
$query = $this->VehicleBrandModels->find();
$query->hydrate(false);
$query->select($this->VehicleBrandModels);
$query->where($cond_arr);
$VBM_data = $query->toArray();
This will generate a query like below
SELECT * FROM vehicle_brand_models WHERE status = 1;
I want to generate a query with nested AND & OR conditions like below
SELECT * FROM vehicle_brand_models WHERE status = 1 AND ((overall_rating > 0 AND overall_rating < 2) OR (overall_rating >= 2 AND overall_rating < 4) OR (overall_rating >= 4 AND overall_rating <= 5));
Can anybody help to solve how to achieve this in CAKEPHP 3.0 Query builder?

The simplest solution is the following
$cond_arr = [
'VehicleBrandModels.status' => 1,
'OR' => [
['overall_rating >' => 0, 'overall_rating <' => 2],
['overall_rating >=' => 2, 'overall_rating <' => 4],
['overall_rating >=' => 4, 'overall_rating <=' => 5]
]
];
there is a more 'cake' way and if I'll have time I will post it.
But note that from what I see all your OR conditions overlap and you can simply do
$cond_arr = [
'VehicleBrandModels.status' => 1,
'overall_rating >' => 0,
'overall_rating <=' => 5
];
edit: as primised here's the more cake way using query expressions
$query->where(function($exp, $q) {
$exp = $exp->eq('VehicleBrandModels.status', 1);
$conditions1 = $exp->and_([])
->gt('overall_rating ', 0)
->lte('overall_rating ', 2);
$conditions2 = $exp->and_([])
->gt('overall_rating ', 2)
->lte('overall_rating ', 4);
$conditions3 = $exp->and_([])
->gt('overall_rating ', 4)
->lte('overall_rating ', 5);
$orConditions = $exp->or_([$conditions1, $conditions2, $conditions3]);
$exp->add($orConditions);
return $exp;
});
still some conditions are overlapping

Related

Yii2: Why Query Builder not return same result as SQL statement?

[UPDATED] Fixed
I have an SQL statement like this
SELECT
jea.subemployer_id,
jea.employer_id,
jea.job_id
FROM
job_employer_assoc AS jea
INNER JOIN job AS j ON jea.job_id = j.job_id
INNER JOIN subemployer AS s ON jea.subemployer_id = s.subemployer_id
WHERE
j.deleted = 0
AND j.klq = 0
AND j.STATUS = 0
AND s.FUNCTION IN ( 0, 1 )
GROUP BY
job_id
And this is my Query Builder:
public function getAllValidEmployerID()
{
$resultQuery = (new Query())
->select(['jea.subemployer_id', 'jea.employer_id', 'jea.job_id'])
->from(['job_employer_assoc AS jea'])
->innerJoin('job AS j', ['jea.job_id' => 'j.job_id'])
->innerJoin('subemployer AS s', ['jea.subemployer_id' => 's.subemployer_id'])
->where(['j.deleted' => 0])
->andWhere(['j.klq' => 0])
->andWhere(['j.status' => 0])
->andWhere(['s.function' => [0, 1]])
->groupBy('job_id')
->all();
return $resultQuery;
}
Why the SQL statement returns values while Query Builder returns an empty array?
I finally find out why, ['jea.job_id' => 'j.job_id'] should be 'jea.job_id = j.job_id'

Yii2 query with and or in where condition

Hi iam trying to covert this query as active record format
SELECT cmaindb, eshdr1, ascsnr, takpplz, takpadr
FROM ts_stats
WHERE (cmaindb = 'tam' OR cmaindb = 'soc')
AND (nproduktiv = 1)
OR (cmaindb = 'tc')
AND (nabrfirm = 5)
AND (nproduktiv = 1)
code which i have tried
return self::find()
->andWhere(['or',
['cmaindb'=> 'tam'],
['cmaindb'=> 'soc']
])
->andWhere(['nproduktiv'=>1])
->orWhere(['cmaindb' => 'tc'])
->andWhere(['nabrfirm '=>5, 'nproduktivs'=>1])
->all();
this will fails
Try this one
$cmaindbs = array('tam'=>'tam', 'soc'=>'soc');
return self::find()
->where(['IN', 'cmaindb' , $cmaindbs])
->andWhere(['nproduktiv' => 1])
->orWhere(['cmaindb' => 'tc'])
->andWhere(['nabrfirm' => 5])
->andWhere(['nproduktivs' => 1])
->all();
Let's further optimize your query:
return self::find()
->where(['IN', 'cmaindb' , ['tam', 'soc', 'tc'])
->andWhere(['nproduktiv' => 1])
->andWhere(['nabrfirm' => 5])
->andWhere(['nproduktivs' => 1])
->all();

Yii2. How to build subexpression

How can i build query with subexpression, without using yii\db\Expression and raw sql. For example this:
SELECT * FROM user WHERE archived = 3 AND ((group = 2 AND status = 3) OR (group = 3 AND status = 2));
You can build such condition using array expressions:
$users = (new Query())
->from('user')
->where(['archived' => 3])
->andWhere([
'or',
[
'group' => 2,
'status' => 3,
],
[
'group' => 3,
'status' => 2,
],
])
->all();

Codeigniter: How to update an amount that will not affect a specific columns

Hi guys I have a problem in my query in model, I'll show you the code before I explain it.
for($x = 1; $x <= count($this->input->post('subparticulars')); $x++) {
$feetype = $this->input->post('subparticulars')[$x];
$student = $this->input->post('substudentid');
$schoolyear = $this->input->post('subschoolyeardata');
$month = $this->input->post('month');
$payment = $this->input->post('subpaymentamount')[$x];
$this->db->set('statement_amount', '`statement_amount` -'. $payment, FALSE);
$this->db->where(array('feetype_id !=' => 2, 'feetype_id !=' => 3, 'feetype_id' => $feetype, 'student_id' => $student, 'schoolyear_id' => $schoolyear, 'month_id' => $month));
$status3 = $this->db->update('tbl_statement');
}
Here I have an add dynamic add row function which has contains the amounts and particulars of multiple payment in subparticulars and subpayments, I'm running a query that will minus my payments in my statement_amounts, as you can see in the $this->db->set. Now, I have a problem with my where clause, if you will try to understand my where clause this is the conditions.
I want to update all my fees except the one that has the feetype_id: 2 and 3, but the other feetype_id will be updated, How can I achieve this. When I'm running the code it still subtracts the fees that have feetype_id of 2 and 3.
Here's the correct answer
for($x = 1; $x <= count($this->input->post('subparticulars')); $x++) {
$feetype = $this->input->post('subparticulars')[$x];
$student = $this->input->post('substudentid');
$schoolyear = $this->input->post('subschoolyeardata');
$month = $this->input->post('month');
$payment = $this->input->post('subpaymentamount')[$x];
if ($feetype == 2 OR $feetype == 3)
{
$this->db->set('statement_amount', '`statement_amount` -'. $payment, FALSE);
$this->db->where(array('feetype_id' => $feetype, 'student_id' => $student, 'schoolyear_id' => $schoolyear));
$status3 = $this->db->update('tbl_statement');
}
else {
$this->db->set('statement_amount', '`statement_amount` -'. $payment, FALSE);
$this->db->where(array('feetype_id' => $feetype, 'student_id' => $student, 'schoolyear_id' => $schoolyear, 'month_id' => $month));
$status3 = $this->db->update('tbl_statement');
}
}

WordPress get specific posts in arbitrary order

Right now, I'm doing:
$posts = get_posts(array('post_type' => 'page', 'post__in' => array(1, 3, 2, 9, 7)));
and am having two issues:
Post 3 is of 'post_type' => 'post', so it doesn't get selected, but I want it! If I leave out 'post_type' => 'page', then only post 3 is selected (because it must assume 'post_type' => 'post'.).
I want to be able to order the posts arbitrarily by their ids. If I knew how to use MySQL, I could do:
SELECT * FROM wp_posts WHERE ID IN (1, 3, 2, 9, 7)
ORDER BY FIND_IN_SET(ID, '1,3,2,9,7');
But, how should I do this with WordPress?
First fetch all posts arbitrarily by their ids and then loop through all the posts
You can do in this way:-
$posts=$wpdb->get_results("SELECT ID FROM $wpdb->posts WHERE ID IN (1, 3, 2, 9, 7)
ORDER BY FIND_IN_SET(ID, '1,3,2,9,7')");
$count=count($posts);
for ($counter=0 ; $counter < $count; $counter++)
{
$post=get_post( $posts[$counter]->ID, $output );
//do your stuffs with posts
}
Hope this helps
Kawauso on the #wordpress IRC channel informed me that "post_type takes an array of values." From that, I found that the following also selects post 3:
So, I did the following:
$post_ids = array(1 => 0, 3 => 1, 2 => 2, 9 => 3, 7 => 4);
$posts = get_posts(array('post_type' => array('post', 'page'),
'post__in' => array_keys($post_ids)));
$ordered_posts = array(0,0,0,0,0); // size of five; keeps order
foreach ($posts as $p) {
setup_postdata($p);
$ordered_posts[$post_ids[$p->ID]] = array(
'permalink' => get_permalink($p->ID),
'title' => $p->post_title,
'excerpt' => get_the_excerpt(),
'date' => date('F j, Y', strtotime($p->post_date)));
}
According to this thread, you can use this code and then use the classic WordPress loop:
$args = array(
'post_type'=>'page',
'orderby'=>'menu_order',
'order'=>'ASC'
);
query_posts($args);