共有3个模型,它们之间存在关联。 例子
class A extends ActiveRecord
{
public static function tableName(){
return 'tbl_a';
}
public function getB()
{
return $this->hasOne(B::className(), ['column' => 'column']);
}
}
class B extends ActiveRecord
{
public static function tableName(){
return 'tbl_b';
}
public function getC()
{
return $this->hasOne(C::className(), ['column' => 'column']);
}
}
我有下一个代码:
$result = A::find()->joinWith('b')->where('');
if () {
A->joinWith('b.c')->where('');
}
$result->createCommand()->rawSql;
结果是我有下一个sql:
select * from tbl_a left join tbl_b on ... join tbl_b on ... join tbl_c on ... where ...
您可以看到sql查询重复表关系'tbl_b'。你知道为什么吗?
更新
好的,我更详细地研究了我的问题。 如果使用不同的JOIN类型,则表连接是重复的。 下一个原始模型:
class Myuser extends ActiveRecord
{
public static function tableName(){
return 'myuser';
}
public function getProfile()
{
return $this->hasOne(Profile::className(), ['user_id' => 'id']);
}
}
class Profile extends \yii\db\ActiveRecord {
public static function tableName(){
return 'profile';
}
public function getCity()
{
return $this->hasOne(City::className(), ['id'=>'city_id']);
}
}
执行的代码:
$get_city = 1;
$u = Myuser::find()->joinWith('profile', 0, 'INNER JOIN');
if ($get_city) {
$u->joinWith('profile.city');
}
echo $u->createCommand()->rawSql;
结果:
SELECT `myuser`.* FROM `myuser`
INNER JOIN `profile` ON `myuser`.`id` = `profile`.`user_id`
LEFT JOIN `profile` ON `myuser`.`id` = `profile`.`user_id`
LEFT JOIN `city` ON `profile`.`city_id` = `city`.`id`
如果我需要获取唯一的表“个人资料”并从表“ city”中添加字段,如何避免重复。如果表“ city”中没有字段,则值应为“ null”。
答案 0 :(得分:0)
我想这是框架中的错误(或功能)。当您使用关系profile.city
框架时,看不到inner join
已经加入的关系...我认为,如果您对第一个关系使用left join
,一切都会很好。
在您的情况下,请尝试使用leftJoin()
并指定要联接的表名:
$get_city = 1;
$u = Myuser::find()->innerJoinWith('profile');
if ($get_city) {
$u->leftJoin('city', 'profile.city_id = city.id');
}
echo $u->createCommand()->rawSql;
答案 1 :(得分:0)
这是因为您为这两个联接使用了不同的联接类型。 joinWith('profile', false, 'INNER JOIN')
和joinWith('profile')
将生成不同的JOIN
(joinWith()
默认使用LEFT JOIN
作为连接类型),因此您有2个查询联接。如果要避免重复,可以对这两个joinWith()
调用使用相同的设置:
$get_city = 1;
$u = Myuser::find()->joinWith('profile', false, 'INNER JOIN');
if ($get_city) {
$u->joinWith('profile.city', false, 'INNER JOIN');
}
echo $u->createCommand()->rawSql;
结果:
SELECT `myuser`.* FROM `myuser` INNER JOIN `profile` ON `myuser`.`id` = `profile`.`user_id` INNER JOIN `city` ON `profile`.`city_id` = `city`.`id`
如果您想结合使用INNER JOIN
和LEFT JOIN
,则可以使用扩展语法:
$get_city = 1;
if ($get_city) {
$u = Myuser::find()->joinWith(
[
'profile' => function (ActiveQuery $query) {
$query->joinWith('city');
},
],
false,
'INNER JOIN'
);
} else {
$u = Myuser::find()->joinWith('profile', false, 'INNER JOIN');
}
echo $u->createCommand()->rawSql;
结果:
SELECT `myuser`.* FROM `myuser` INNER JOIN `profile` ON `myuser`.`id` = `profile`.`user_id` LEFT JOIN `city` ON `profile`.`city_id` = `city`.`id`