今天需要实现一个比较复杂的SQL,需要LEFT JOIN扩展字段表的工单ID,同时还要匹配扩展字段的值
首先我们把工单表的主键ID和扩展字段的item_id关联起来
public function getExt_field() { /** * 第一个参数为要关联的字表模型类名称, *第二个参数指定 通过子表的 item_id 去关联主表的 id 字段 */ return $this->hasMany(BbItemExtFieldData::className(), ['item_id' => 'id']); }
我们通过joinWith就可以关联这两张表了,并实现对工单表的搜索条件约束
BbItem::find()->asArray()->joinWith('ext_field')->where([BbItem::tableName().'.status'=>'1'])->andWhere($where);
然后我们需要把扩展字段的约束条件加上,如果我们的扩展字段表的字段名是扩展字段的名称那么就很好办,不过问题是:
扩展字段表是通过tablekey_name来存储,自定义字段的字段名的
所以我们需要添加 … AND ( (表名.tablekey_name=’字段名’ AND 表名.value=’搜索值’) OR (表名.tablekey_name=’字段名’ AND 表名.value=’搜索值’))的SQL来进行约束
查了半天YII2的手册,终于找到了正确的实现方法:
//进行搜索 $query = BbItem::find()->asArray()->joinWith('ext_field')->where([BbItem::tableName().'.status'=>'1'])->andWhere($where); //追加扩展字段条件 $ext = ['OR']; foreach($category_info['ext_field'] as $k => $one) { if(isset($ext_where[$one['table_keyname']])) { $table_key_name = $one['table_keyname']; $ext[] = ['AND', BbItemExtFieldData::tableName().'.table_keyname=\''.$table_key_name.'\'', BbItemExtFieldData::tableName().'.value=\''.$ext_where[$table_key_name].'\'', BbItemExtFieldData::tableName().'.ext_id=\''.$one['id'].'\'']; } } $query->andWhere($ext);
这样实现出来的sql是
SELECT `bb_item`.* FROM `bb_item` INNER JOIN `bb_item_ext_field_data` ON `bb_item`.`id` = `bb_item_ext_field_data`.`item_id` WHERE `bb_item`.`status`='1' AND `bb_item`.`category_id`='8' AND ((`bb_item_ext_field_data`.`table_keyname`='ext_field3' AND `bb_item_ext_field_data`.`value`='选项1|选项2' AND `bb_item_ext_field_data`.`ext_id`='5') OR (`bb_item_ext_field_data`.`table_keyname`='ext_field4' AND `bb_item_ext_field_data`.`value`='选项1' AND `bb_item_ext_field_data`.`ext_id`='6'))