【问题标题】:UNION syntax in CakephpCakephp 中的 UNION 语法
【发布时间】:2010-08-21 03:07:48
【问题描述】:

谁知道在 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

【问题讨论】:

  • 您是否有任何理由希望避免使用 $this->query?
  • 好吧,首先,如果您不打算尝试以框架的本机样式编写应用程序,那么它就违背了使用框架的目的。而大多数SELECT 查询实际上可以在1.3 中使用find() 执行。此外,find() 受益于数据源驱动程序对 SQL 注入的内置保护,而 query() 是您必须自己逃避的直接查询。也就是说,UNION 可能是您无法使用 find() 执行的少数几类查询之一。
  • 您是否有正在运行的有效 MySQL 联合示例?列出的那个不起作用。
  • 我认为对于框架的目的有些混淆。框架不一定设计为使您的代码跨数据库兼容。此外,您不应将站点的功能限制在框架内的限制范围内。框架旨在将 UI 与域逻辑分开。它还通过引入结构和组织来增强开发,并提供可重用的代码。如果你只做框架允许的事情,你将限制你的能力。
  • @cdburges:我还没有工作示例。事实上我需要做FULL JOIN 但 MySQL 不支持。所以,我认为我不是第一个遇到这个问题的人,可能已经找到了解决方案,因此我发布了这个问题。

标签: php sql mysql cakephp union


【解决方案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);

【讨论】:

    【解决方案2】:

    我们目前使用的一种简单方法是在 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 版。

    【讨论】:

    • 这是一个非常好的解决方案
    【解决方案3】:

    太多的程序员试图将自己限制在框架的功能上。不。使用框架提供的内容。如果它没有您想要的功能,那么:

    • 将您需要的功能编码到类扩展中

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

    通常情况下,开发人员会尝试将方形钉子敲入圆孔,最终会做太多额外的工作,而这实际上只会使代码变得复杂。退后一步,问问你为什么一开始就使用这个框架。它为非结构化语言带来了结构。它为构建您的应用程序提供了坚实的可重用基础。它并不打算成为一个让自己置身于其中并受到限制的盒子。

    更新:我花了一分钟阅读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 表示更新。这是正确的方向。稍后我会仔细查看代码。
    • 点赞建议开发人员不要将自己限制在框架提供的功能上。我看到太多次人们因为“这不是蛋糕方式”而忽略了一个完全有效的解决方案。
    【解决方案4】:

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

    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
    

    【讨论】:

    • 这是一个很好的解决方案,但请参阅关于在 Cake 中使用视图的免责声明:mail-archive.com/cake-php@googlegroups.com/msg43116.html
    • 恐怕这在 SQLlite 等其他数据库中不起作用。
    • @bancer:你确定吗? SQLite 的文档表明它支持视图并使用相同的create view 语法。
    • 我的意思是RIGHT JOIN。也许我的查询完全不依赖于数据库?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    相关资源
    最近更新 更多