2018-08-19 18:12:40 2493次浏览 3条回答 0 悬赏 20 金钱

有5张数据表:

会员表 member

CREATE TABLE member (

 id int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
 
 name varchar(128) NOT NULL COMMENT '名字',
 
 created_at int(11) DEFAULT NULL COMMENT '创建时间',
 
 PRIMARY KEY (id)
 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='会员'

课程表 course

CREATE TABLE course (

 id int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
 
 name varchar(128) NOT NULL COMMENT '课程名称',
 
 created_at int(11) DEFAULT NULL COMMENT '创建时间',
 
 PRIMARY KEY (id)
 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='课程'

考试表 exam

CREATE TABLE exam (

 id int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
 
 name varchar(128) NOT NULL COMMENT '名称',
 
 created_at int(11) DEFAULT NULL COMMENT '创建时间',
 
 PRIMARY KEY (id)
 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='考试'

下载资源 resource

CREATE TABLE resource (

 id int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
 
 name varchar(128) NOT NULL COMMENT '名称',
 
 created_at int(11) DEFAULT NULL COMMENT '创建时间',
 
 PRIMARY KEY (id)
 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='考试'

订单表 order

CREATE TABLE `order` (

 `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
 
 `type` int(11) NOT NULL COMMENT '会员ID',
 
 `goods_id` int(11) NOT NULL COMMENT '商品ID',
 
 `member_id` int(11) NOT NULL COMMENT '用户ID',
 
 `credit` int(11) NOT NULL COMMENT '积分值',
 
 `created_at` int(11) DEFAULT NULL COMMENT '变更时间',
 
 PRIMARY KEY (`id`),
 
 KEY `fk_order_owner` (`member_id`),
 
 CONSTRAINT `fk_order_owner` FOREIGN KEY (`member_id`) REFERENCES `member` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 
) ENGINE=InnoDB AUTO_INCREMENT=90 DEFAULT CHARSET=utf8mb4 COMMENT='订单表'

其中,订单表保存了课程、考试、资源的订单,具体说Order订单表各字段:

id: 主键

type: 类型,1为课程订单,2为考试订单, 3为资源订单

goods_id: 商品id

   在type == 1时,该字段值为course.id; 
   
   在type == 2时,该字段值为exam.id; 
   
   type == 3时,该字段值为resource.id

user_id: 用户id

TIM截图20180819185554.jpg

现在的需求:在订单管理功能中能够根据商品的名称搜索出对应订单

这里商品的名称根据订单的类型不同,可能是课程名称、考试名称、资源名称。

手写能实现预期效果SQL语句(查询关键词为:名):

`SELECT *` 

`FROM  order`

`LEFT JOIN course ON  order.goods_id = course.id AND  order.type =1`

`LEFT JOIN exam ON  order.goods_id = exam.id AND  order.type =2`

`LEFT JOIN resource ON  order.goods_id = resource.id AND  order.type =3`

`WHERE course.name like '%名%' or exam.name like '%名%' or resource.name like '%名%'`

如果在OrderSearch.php中用AR该怎么写呢,特别是像

LEFT JOIN course ON order.goods_id = course.id AND order.type =1

这样的关联条件,Yii2是不是不支持?

// $query->joinWith('exam')

// ->joinWith('course')

// ->joinWith('resource');
  • 回答于 2018-08-20 09:39 举报

    支持的,
    比如你Order模型里定义了:

    public function getCourse(){
        return $this->hasOne(Course::className(),['id'=>'goods_id'])
            ->onCondition(['type'=>1]);
    }
    

    那你query里就可以用

    $query->joinWith('course');
    

    如果你要按course的name来搜索,可以用函数回调,比如:

    $query->innerJoinWith([
        'course' => function ($query) {
            $query->andFilterWhere(['like', 'name', $this->coupon_name]);
        }
    ]);
    
    2 条回复
    回复于 2018-08-20 09:52 回复

    这种方法在提问之前试过,onCondition(['type'=>1]) 会生成 course.type=1 而不是 order.type=1 不是想要的结果;而且$query->joinWith('course')->onCondition(['type'=>1])这种也试过,是在最后生成where条件也不是想要的结果。
    目前看AR好像是不支持的。

    回复于 2018-08-20 10:39 回复

    yii\db\Expression 了解一下

  • 回答于 2018-08-20 15:27 举报

    试下leftJoin('course' , 'order.goods_id = course.id AND order.type =1')....这种写法。个人想法

  • 回答于 2018-08-20 18:45 举报

    我觉得你的数据库设计让简单的问题复杂化了,课程、考试和下载资源三个表都属于商品,放在一个表格(假设叫 item )内存储就行了。把 order.type 迁移到 item 表内,整个结果会更清晰一些。

    2 条回复
    回复于 2018-08-21 08:31 回复

    课程、考试和下载资源,如果都放到一张表中,用type来表示不同的类别,那么会不会影响数据库的效率?再就是并发更新,是否会受影响

    回复于 2018-08-21 14:11 回复

    这个看个人取舍,问题是你现在的设计方法让搜索商品名这个常用操作的查询效率变得不高,也会影响到数据库的性能。

您需要登录后才可以回答。登录 | 立即注册
Jason571
助理

Jason571

注册时间:2016-01-04
最后登录:2018-10-12
在线时长:6小时8分
  • 粉丝1
  • 金钱40
  • 威望0
  • 积分100

热门问题