Cakephp中的UNION语法

时间:2010-08-21 03:07:48

标签: php sql mysql cakephp union

任何人都知道在CakePHP中进行UNION查询的好方法吗?我想避免使用$this->query();

有两个表t1,t2:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

有三个表t1,t2,t3:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
RIGHT JOIN t3 ON t2.id = t3.id

4 个答案:

答案 0 :(得分:13)

太多的程序员试图将自己局限于框架的功能。别。使用框架提供的内容。如果它没有您寻求的功能,那么:

  • 将您需要的功能编入类扩展

  • 自定义在框架内旋转代码以满足您的需求。

通常情况下,开发人员会尝试将方形钉子敲入一个圆孔中,然后做太多额外的工作,这实际上只会使代码变得复杂。退后一步,问一下为什么要开始使用框架。它为非结构化语言带来了结构。它为构建应用程序提供了坚实的可重用基础。它并不是一个让自己陷入困境的盒子。

更新:我花了一分钟时间阅读Complex Find Conditions并找到了答案:

$joins = array(
    array(
        'table' => 'test_twos',
        'alias' => 'TestTwo',
        'type' => 'LEFT',
        'conditions' => array(
            'TestTwo.id = TestOne.id',
        )
    ),
    array(
        'table' => 'test_threes',
        'alias' => 'TestThree',
        'type' => 'LEFT',
        'conditions' => array(
        'TestThree.id = TestOne.id',
    )
    )
);

$dbo = $this->getDataSource();
$subQuery = $dbo->buildStatement(
    array(
        'fields' => array('*'),
        'table' => $dbo->fullTableName($this),
        'alias' => 'TestOne',
        'limit' => null,
        'offset' => null,
        'joins' => $joins,
        'conditions' => null,
        'order' => null,
        'group' => null
    ),
    $this->TestOne
);
$query = $subQuery;

$query .= ' UNION ';
$joins = array(
    array(
        'table' => 'test_twos',
        'alias' => 'TestTwo',
        'type' => 'LEFT',
        'conditions' => array(
            'TestTwo.id = TestOne.id',
        )
    ),
    array(
        'table' => 'test_threes',
        'alias' => 'TestThree',
        'type' => 'RIGHT',
        'conditions' => array(
        'TestThree.id = TestOne.id',
        )
    )
);

$dbo = $this->getDataSource();
$subQuery = $dbo->buildStatement(
    array(
    'fields' => array('*'),
    'table' => $dbo->fullTableName($this),
    'alias' => 'TestOne',
    'limit' => null,
    'offset' => null,
    'joins' => $joins,
    'conditions' => null,
    'order' => null,
    'group' => null
    ),
    $this->TestOne
);

$query .= $subQuery;

pr($query);

答案 1 :(得分:5)

我们目前使用的一种简单方法是在MySQL或您使用的任何数据库中创建视图。然后,您可以使用视图,而不是在模型中使用表格。您可以在此处阅读有关视图创建语法的信息:http://dev.mysql.com/doc/refman/5.6/en/create-view.html。您还可以使用HeidiSQL等软件来帮助您创建视图。

您的模型中会有这样的内容:

class Contenu extends AppModel {
    public $useTable = 'v_contenu';

这允许你仍然使用CakePHP中的find()方法,这非常好。

要获得视图的最佳性能,您应该将MySQL更新到至少5.6版本。

答案 2 :(得分:3)

使用视图,然后从中选择:

create view my_union as
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
LEFT JOIN t3 ON t2.id = t3.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
RIGHT JOIN t3 ON t2.id = t3.id

在您的代码中:

select * from my_union

答案 3 :(得分:1)

使用这样的代码:

$friendsPosts= $this->Posts->find('all')
                ->contain(['Users', 'Languages', 'PostStates'])
                ->innerJoinWith('Users.Dusers', function ($q) {
                    return $q->where(['Dusers.id' => $this->Auth->user('id')]);
                });

        $posts= $this->Posts->find('all')
                ->where(['Posts.post_state_id' => 3])
                ->contain(['Users', 'Languages', 'PostStates']);

    $posts->union($friendsPosts);