I have a following SQL query which I want to "build" with the ORM of Yii2:
SELECT * FROM table WHERE [some conditions] AND (col1 <> 0 OR col2 <> 0)
So I want to exclude all results where col1 and col2 equals 0, but I don't want to do this with the SQL EXCEPT command.
The SQL should be correct, but my question is now how to build that with the yii2 ORM.
You need to use condition in one array with key 'OR'
Model::find()
->where(['condition' => 1])
->andWhere([
'OR',
['!=', 'col1', 'val1'],
['!=', 'col2', 'val2'],
])
->all();
Use this code:
Model::find()->where(['condition' => 1])
->andWhere(['condition2' => 20])
->andWhere(['not', ['col1' => 0]])
->andWhere(['not', ['col2' => 0]])
->all();
Related
I have these 2 tables : keyword and keyword_translated
keyword
id
name
keyword_translated
id
translation
keyword_id
I want to get all keyword, doesn't matter has or not relation with keyword_translated. At the end I want to get something like :
[
[
keyword_id => 1,
keyword_name => 'firstKeyword'
keyword_translated_id => 1, // if exist relation between `keyword` and `keyword_translated`
keyword_translated_translation => 'This is translation of firstKeyword' // if exist relation between `keyword` and `keyword_translated`
],
[
keyword_id => 2,
keyword_name => 'secondKeyword'
keyword_translated_id => null, // if didn't exist relation between `keyword` and `keyword_translated`
keyword_translated_translation => null // if didn't exist relation between `keyword` and `keyword_translated`
],
]
I tried like this :
$keywords = DB::table('keywords')
->join('keywords_translated', 'keywords.id', '=', 'keywords_translated.keyword_id')
->select('keywords.*', 'keywords_translated.*')
->get();
But I have empty data. What can I try to resolve this?
use leftjoin instead of join like this:
$keywords = DB::table('keywords')
->leftjoin('keywords_translated', 'keywords.id', '=','keywords_translated.keyword_id')
->select(
'keywords.id as keyword_id',
'keywords.name as keyword_name',
'keyword_translated.id as keyword_translated_id',
'keyword_translated.translation as keyword_translated_translation',
)
->get();
Save this image for future reference.
How can I get all the instances of a Table where the fields are not NULL ?
Here is the configuration:
I have a Table 1 where the instances have a relationship "hasmany" with a Table 2. I want to get all the instances of Table 1 linked with a Table 2 instance not NULL.
The CakePHP doc helped me finding the exists() and isNotNull() conditions but I did not achieve.
Here is how I imagined:
$Table1 = TableRegistry::get('Table1')->find('all')->contain([
'Table2' => [
'sort' => ['Table2.created' => 'desc']
]
])->where([
'Table1.id' => $id,
'Table2 IS NOT NULL'
]);
$this->set(compact('Table1'));
But it obviously does not work.
edit : I expect to get all the line of the Table1 which contain existing Not NULL Table2 line(s) linked. The problem is in the 'where' array with the 'Table2 IS NOT NULL', it does not work.
And without this line 'Table2 IS NOT NULL', I get all the Table1 line which contain a Table2 line or not (because some line of Table1 are not linked at all and I don't want to get these lines).
Assuming the tables follow convention and use "id" as the primary key, I suggest the easiest fix would be testing that field for NOT NULL.
I.e., replace this:
'Table2 IS NOT NULL'
with this:
'Table2.id IS NOT NULL'
or:
'Table2.id !=' => null
or:
'Table2.id >' => 0
I've successfuly get the Table1 lines with its existing Table2 line(s) associated.
query = TableRegistry::get('Table1')->find();
$query->select(['Table1.id', 'count' => $query->func()->count('Table2.id')])->matching('Table2')->group(['Table1.id'])->having(['count
>' => 0]);
$table1Ids = [];
foreach ($query as $z)
{
$table1Ids[] = $z->id;
}
$table1= TableRegistry::get('Table1')->find('all')->contain([
'Table2' => [
'sort' => ['Table2.created' => 'desc']
]
])->where([
'id IN' => $table1Ids,
]);
Here is my correct sql query:
SELECT * FROM `messages` WHERE ( (sender_id=3 AND user_id=40) OR (sender_id=40 AND user_id=3)) AND offer_id=1
I want to use this in Cakephp syntax:
$this->Message->find('all',array('conditions'=>array(
'AND'=>array(
'OR'=>array(
'Message.offer_id'=>$offer_id,
'Message.sender_id'=>$sender_id,
'Message.user_id'=>$this->Auth->user('id'),
),
'OR'=>array(
'Message.offer_id'=>$offer_id,
'Message.user_id'=>$sender_id,
'Message.sender_id'=>$this->Auth->user('id')
)
)
),
'recursive'=>2
));
Is there anyone who can help me to figure out the issue. Basically I want to get all the messages whether I sent or received for an particular offer.
You should move $offer_id out of or conditions and move it to and conditions.
Why? Lets look at your first or array:
That conditions will return true if:
sender_id is 3
OR user_id is 40
OR offer_id is 1
So, that condition may return true event if offer_id != 1
That should be written this way (as precisely as possible according to original query):
$query = $this
->Messages
->find('all' , [
'conditions' => [
'or' => [
[
'sender_id' => $sender_id,
'user_id' => $this->Auth->user('id')
], [
'sender_id' => $this->Auth->user('id'),
'user_id' => $sender_id
]
],
'offer_id' => $offer_id,
]
]);
dump($query);
In dump we can see something like this:
"SELECT * FROM messages Messages WHERE (((sender_id = :c0 AND user_id = :c1) OR (sender_id = :c2 AND user_id = :c3)) AND offer_id = :c4)
asterisk in sql query dump for more readability
You have the AND and OR operators reversed.
'OR'=>array(
'AND'=>array(
'Message.offer_id'=>$offer_id,
'Message.sender_id'=>$sender_id,
'Message.user_id'=>$this->Auth->user('id'),
),
'AND'=>array(
'Message.offer_id'=>$offer_id,
'Message.user_id'=>$sender_id,
'Message.sender_id'=>$this->Auth->user('id')
)
)
Hi i want to use not null condition in my yii2 query how should i use that.
i don't want city and state null.
My query is
$query = new Query;
$query->select('ID, City,State,StudentName')
->from('student')
->where(['IsActive' => 1])
->orderBy(['rand()' => SORT_DESC])
->limit(10);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false,
]);
You can use the not operator combined with the fields that should not be null to generate a IS NOT NULL SQL statement. Like this:
$query = new Query;
$query->select('ID, City,State,StudentName')
->from('student')
->where(['IsActive' => 1])
->andWhere(['not', ['City' => null]])
->andWhere(['not', ['State' => null]])
->orderBy(['rand()' => SORT_DESC])
->limit(10);
Also check the examples in the documentation.
->where(['IS NOT', 'column', null]);
get
WHERE column IS NOT NULL
You can also use, it is faster to type
->where('column IS NOT NULL')
In complex query
->where(['AND',
'column1 IS NOT NULL', // works
['IS NOT', 'column2', null], // works
['column3' => $value],
)
One of the options will be:
$query = new Query;
$query->select('ID, City,State,StudentName')
->from('student')
->where(['IsActive' => 1])
->andWhere(['<>', 'City', null])
->andWhere(['<>', 'State', null])
->orderBy(['rand()' => SORT_DESC])
->limit(10);
Check official docs for where.
$items = BadOffer::find()->where(['OR',
['IS', 'moderator_id', (new Expression('Null'))],
['moderator_id' => $user->id],
]);
In Yii2, we can use any of the queries below to verify the null condition,
->andWhere(['NOT', ['city' => null]]);
or
->andWhere(['<>', ['city' => null]]);
or
->andWhere('city IS NOT NULL');
use ->andWhere(['not', ['State' => null]]) or ->andWhere(['is not', 'State', null]);
Do no use :
andFilterWhere, as the null will make this filter be ignored
->andWhere(['<>', 'State', null]) as it form query AND State <> null
How to select non-empty columns in MySQL?
use LENGTH :
SELECT col1
FROM table
WHERE LENGTH(col1) > 0
Yii2 :
->andWhere(['>', 'LENGTH(col1)', 0])
This work for me, but only when pass null as string
->andFilterWhere(['<>', '`city`', 'null']);
I'm trying to make query builder to output the following MySQL query:
SELECT p1.id, p1.product_id, p1.updated_at
FROM tbl_scrape_data p1
INNER JOIN
(
SELECT max(updated_at) MaxDate, product_id
FROM tbl_scrape_data
WHERE product_id IN (1,2,3)
GROUP BY product_id
) p2
ON p1.product_id = p2.product_id
AND p1.updated_at = p2.MaxDate
WHERE p1.product_id IN (1,2,3)
order by p1.updated_at desc
Here's what I tried:
$scrapeData = (new Query() )
->select(['p1.product_id', 'p1.id', 'p1.updated_at'])
->from('tbl_scrape_data p1')
->innerJoin([
'p2' => (new Query)
->select(['MAX(updated_at) MaxDate', 'product_id' ])
->from('tbl_scrape_data')
->where([ 'product_id' => [1, 2, 3, 15, 4] ])
->groupBy('product_id'),
//->all(),
['p1.product_id' => 'p2.product_id', 'p1.updated_at' => 'p2.MaxDate']
])
->where([ 'p1.product_id' => [1, 2, 3, 15, 4] ])
->orderBy('p1.updated_at DESC')
->all();
Yii2 throws an error trying to perform this query. Can someone tell me if this is a Yii2 bug or if I'm missing something? Or maybe the way I formatted the query builder is wrong?
I'm using Yii 2.0.1 and the error is
strpos() expects parameter 1 to be string, array given
\vendor\yiisoft\yii2\db\QueryBuilder.php at line 715
The reason of the error is in this section of code:
->innerJoin([
'p2' => (new Query)
->select(['MAX(updated_at) MaxDate', 'product_id' ])
->from('tbl_scrape_data')
->where([ 'product_id' => [1, 2, 3, 15, 4] ])
->groupBy('product_id'),
//->all(),
['p1.product_id' => 'p2.product_id', 'p1.updated_at' => 'p2.MaxDate']
])
Instead of passing two parameters - table and on separately you actually passing them in one parameter - array.
Also the first parameter (table) should be array with one element.
In other words, the placement of square brackets is incorrect.
So here is correct code of the INNER JOIN section:
->innerJoin(
['p2' => (new Query)
->select(['MAX(updated_at) MaxDate', 'product_id' ])
->from('tbl_scrape_data')
->where([ 'product_id' => [1, 2, 3, 15, 4] ])
->groupBy('product_id'),
//->all(),
],
['p1.product_id' => 'p2.product_id', 'p1.updated_at' => 'p2.MaxDate']
)
Check the official documentation for innerJoin() method.