MySQL Union全部在Yii的默认范围内

时间:2015-01-15 03:42:37

标签: php mysql yii

我正在使用Yii 1.1.16,并且想知道我的联盟2型号将如何使用默认范围?

model 1 = abc
model 2 = abc2

基本上我想做一个简单的联合

SELECT * FROM `abc`
UNION ALL
SELECT * FROM `abc2`

还没有真正使用默认范围,所以对这个概念有点新意。 两个表都具有完全相同的列号和列名。

我试过这个,但失败了。

在我的abc模型中

public function defaultScope() {
        return array(
            'alias' => 't2',
            'select'=>array('t.*, t2.*'),
            'union'=>array('SELECT * FROM `abc2`')
        );
    }

更新 刚刚意识到http://www.yiiframework.com/doc/api/1.1/CDbCriteriaunion没有CDbCriteria

public function defaultScope() {
        return array(
            //'alias' => 't',
            'select'=>array('*'),
            'join'=>'UNION ALL SELECT * FROM `abc2`'
        );
    }

上面的代码给我一个错误

CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.make_code' in 'where clause'. The SQL statement executed was: SELECT `t`.`class_code`, `t`.`make_code`, `t`.`model_code` FROM `abc` `t` UNION ALL SELECT * FROM `abc2` WHERE `t`.`make_code`=:yp0 LIMIT 1. Bound with :yp0='11' 

在两个表中,我都有列make_code

我需要查询看起来像这样

SELECT * FROM 
(
   SELECT * FROM `abc` 
      UNION ALL 
   SELECT * FROM `abc2`
) AS t 

如何解决这个问题?

5 个答案:

答案 0 :(得分:3)

您可以使用Yii query builder;它是您需要构建非标准查询的首选解决方案,它本身支持UNION

$data = Yii::app()->db->createCommand()
  ->select('*')
  ->from('abc')
  ->union('SELECT * FROM `abc2`')
  ->where('make_code=:make_code', [':make_code'=>42])
  ->queryAll();

或者,您可以使用->getText()或手动编写SQL,然后使用CSqlDataProvider创建可配置的数据源,而不是直接查询。

答案 1 :(得分:2)

你好,我希望我能帮到你, 现在,yii 1.x的cdbcriteria尚未为工会做好准备...所以我想更多关于其他解决方案或wa。

所以,解决这个问题的简单方法是根据您需要的查询创建一个视图:

CREATE VIEW unionAbc AS
SELECT * FROM `abc` 
UNION ALL 
SELECT * FROM `abc2`

然后从那个视图中你可以构建一个新模型并且不费力地调用它。

我发现的另一个解决方案是合并模型查询结果,这是我从php理论的角度告诉你的,我的意思是当你在yii中生成模型查询时它返回一个数组或对象,你将需要使用yii helper中存在的模型中的数组转换器,然后合并两个数组,这样就会产生一个带有两个数据的新数组

未经测试的第三种解决方案是:

$dataProvider =  new CArrayDataProvider('User');
$dataProvider->setData($modelabc->findAll());
$dataProvider->setData($modelabc2->findAll());

问候。

答案 2 :(得分:2)

我建议KISS解决方案:
是否有可能从联合选择创建视图并使用它?
然后从该视图创建Active Record。 当然,对于UI中的创建/删除数据,您必须在两个表中单独创建模型。

更新
您可以在数据库中创建视图: CREATE VIEW abc_union AS SELECT * FROM abc UNION ALL SELECT * FROM abc2
然后使用Gii为此视图生成模型。

答案 3 :(得分:1)

首先,如果数据库中有2个相同的表,可能最好将它们合并为一个。 Yii基于简单规则的ActiveRecord实现:一个表 - >一个活跃的记录模型。

我建议你使用存储库模式这个解决方案。我不认为使用defaultScope()是必不可少的。

1.创建一个界面以确保两个产品模型都实现了一些常用的方法。

interface Product
{
    public function findAllByMakeCode($makeCode);

    // other common methods here
}

2.使用您需要的常用方法实现或默认范围创建特征。

trait ProductTrait
{
    function findAllByMakeCode($makeCode)
    {
        return $this->model()->findAllByAttributes(['make_code' => $makeCode]);
    }

    function defaultScope()
    {
        // your default scope condition
        // for example field is_deleted equals to 0
        return ['condition' => 'is_deleted=0'];
    }
    // other common methods implementation
}

3.为两个表创建单独的AR模型。

// used product entity
class ProductUsed extends CActiveRecord implements Product
{
    use ProductTrait;

    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    public function tableName()
    {
        return 'product_used';
    }
}

// new product entity
class ProductNew extends CActiveRecord implements Product
{
    use ProductTrait;

    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    public function tableName()
    {
        return 'product_new';
    }
}

4.创建一个Repository类。

class ProductRepository
{   
    public function findAllByMakeCode($makeCode)
    {
        return array_merge(
            ProductUsed::model()->findAllByMakeCode($makeCode),
            ProductNew::model()->findAllByMakeCode($makeCode)
        );
    }

    public function findAll($condition = '', array $params = [])
    {
        return array_merge(
            ProductUsed::model()->findAll($condition = '', array $params = []),
            ProductNew::model()->findAll($condition = '', array $params = [])
        );
    }
}

5.使用它。

$repository = new ProductRepository();

// all products
$products = $repository->findAll();

// products with 42 make code
$products42 = $repository->findAllByMakeCode(42);

也许它看起来有点复杂,但值得。

答案 4 :(得分:1)

你可以像这样使 UNION ;

$firtQuery = Yii::app()->db->createCommand()
    ->select("*")
    ->from('abc')
    //->where() you can add WHERE clause in here
    ->getText();

$result = Yii::app()->db->createCommand()
    ->select("*")
    ->from('abc2')
    //->where() you can add WHERE clause in here
    ->union($firtQuery)
    ->queryRow();