Yii2. How to build subexpression - yii2

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();

Related

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();

CakePHP 3.6 Query Builder complex OR conditions issue

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

cakephp query find_in_set on single column with multiple searched keywords not working

I want to find all the records from column who have any keyword match with column data:
It works fine if searching single search keyword in column having comma separated values like below code: Cakephp 3.4 version
$posts = TableRegistry::get('Posts');
$search_keywords = array_filter(explode(' ', $search_string));
$option = [
'contain' => false,
'conditions' => [
"find_in_set('New', Posts.title)",
],
'order' => ['Posts.created DESC']
];
$allpost = $posts->find('all',$option)->toArray();
Note: i want all the words from string should be search with column title, its not mandatory to have comma separated records:
$search_keyword = "New car in new delhi";
so i want code to be like below :
$search_keyword = "New car in new delhi";
$search_keywords = array_filter(explode(' ', $search_string));
$option = [
'contain' => false,
'conditions' => [
"find_in_set({$search_keywords}, `Posts`.title)",
],
'order' => ['Posts.created DESC']
];
$allpost = $posts->find('all',$option)->toArray();
Great Thanks in advance!!!
I found the solution:
First make column fulltext index then add below code:
$search_string = "New car in new delhi";
$option = [
'contain' => false,
'conditions' => [
"MATCH (title) AGAINST ('$search_string')"
],
'order' => ['Posts.created DESC']
];
$allpost = $posts->find('all',$option)->toArray();

elastic search: Advanced Filter Query

I am Working on Elastic Search for My current Project. I need a filter for users based on their industries. please look at my code once. and mySql query as follows
SELECT U.* FROM `users` `U`
JOIN `user_industries` `UI` ON `UI`.`user_id`=`U`.`id`
WHERE `UI`.`industry_id` IN('1','3','5');
$query = array("from" => $start,
"size" => $recordslimit,
"sort" => array(array('id' => 'desc')),
"query" => array(
"filtered" => array(
"query" => array("match_all" => array()),
"filter" => array(
"bool" => array(
'must' => array(array('term' => array('user_type' => 'v')),
array('term' => array('status' => 'a')),
array('term' => array('industries.id' => 1))
),
'must_not' => array(
array('term' => array('subscription_type' => 'n'))
)
))
)));
I passed one Industry Value. how can i pass multiple values of industries
Great start !! You can achieve what you want by using a terms filter instead of a term one and specifying the values 1, 3, 5 in an array():
...
array('terms' => array('industries.id' => array(1, 3, 5)))
...

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);