Php Yii2-多重条件下的左连接
我有三张表,它们的关系如下:Php Yii2-多重条件下的左连接,php,mysql,yii2,Php,Mysql,Yii2,我有三张表,它们的关系如下: ------- 1 0..* ------------ |Product|-------------|Availability| ------- ------------ 1 | | 1 | -------- |MetaData| -------- 我的原始sql如下所示 SELECT p.ID FROM product p LEFT JOIN availability a
------- 1 0..* ------------
|Product|-------------|Availability|
------- ------------
1 |
|
1 |
--------
|MetaData|
--------
我的原始sql如下所示
SELECT p.ID FROM product p
LEFT JOIN availability a ON a.productID=p.ID
AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)
LEFT JOIN meta_data m ON m.ID=p.meta_dataID
WHERE a.ID IS NULL
AND m.published_state=1;
也就是说,查找具有元数据的产品。发布状态等于1
且不具有可用性的产品。可用性。从开始超过7天(
)
我正在尝试使用ActiveRecord
方法来完成同样的任务,使用类似以下的方法
$products = Product::find()
->joinWith('metaData')
->joinWith('availability')
->onCondition(['>=', 'availability.start', strtotime('+7 days')])
->where(['is', 'availability.ID', NULL])
->andWhere(['=', 'meta_data.published_state', 1])
->all();
然而,这并没有产生任何结果。使用Connection::createCommand()
运行原始sql将返回我期望的行,因此数据没有问题
我怀疑问题是由join
条件和where
条件相互“出血”引起的;联接和where都应用于联接或where,而不是单独应用
如何输出正在运行的实际sql查询?这是在从控制台控制器调用的操作中
如何更改代码以返回所需的产品
?只需按以下条件使用即可
$query = Product::find()
-> leftJoin('availability', 'availability.productID=product.ID AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)')
->leftJoin('meta_data', 'meta_data.ID=product.meta_dataID')
->where(['is', 'availability.ID', NULL])
->andWhere(['=', 'meta_data.published_state', 1])
->all();
我相信这是一个更好的解决方案。不要使用像leftJoin
这样的原始查询,而应该使用andOnCondition
的关系来补充join(这会在join语句中添加所需的where条件)
此外,在关系中编写where
子句时,它看起来更干净。它的工作原理与在外部写入相同(如果我没有错的话),但在重构查询时,您可以轻松删除整个关系,而不会忘记外部的关系条件。使用以下方法:
$sql = 'SELECT p.ID FROM product p
LEFT JOIN availability a ON a.productID=p.ID
AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)
LEFT JOIN meta_data m ON m.ID=p.meta_dataID
WHERE a.ID IS NULL
AND m.published_state=1';
$products = Product::findBySql($sql);
Yii Active Record有一个方法,允许您使用原始SQL查询从数据库中运行和获取数据。当您对Yii的查询方法感到困惑时,或者当您的查询使用Yii运行时变得更加复杂时,我想这会有很大帮助
因此,基本上,在上面的代码块中,您只需将原始SQL查询放入一个名为$SQL
的变量,并将其用作findBySql()
方法的参数值。它只提供产品的数据,而不提供可用性和元数据。如何在结果中同时显示这两个关系。您使用的是原始的LeftJoin,而不是Yii2关系。最好用额外的条件来补充目前的关系。非常非常有帮助。只需注意ActiveQuery
名称空间是\yii\db\ActiveQuery
,请编辑您的答案,包括此代码如何工作以及如何解决问题的解释。已编辑。希望能有帮助。
$sql = 'SELECT p.ID FROM product p
LEFT JOIN availability a ON a.productID=p.ID
AND a.start>=DATE_ADD(DATE(now()), INTERVAL 7 DAY)
LEFT JOIN meta_data m ON m.ID=p.meta_dataID
WHERE a.ID IS NULL
AND m.published_state=1';
$products = Product::findBySql($sql);