我正在使用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/CDbCriteria
,union
没有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
如何解决这个问题?
答案 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();