好好爱自己!

cakephp , the subquery (2)

Cakephp 框架帮我们做了很多的工作,的确省了我们很多工作,提高了效率。

但是,碰到一些比较复杂的查询时,还是有些问题,官方的cookbook api 有说明一些详细的用法,但感觉还是不太够,有些地方讲的不够清楚。

StackOverflow上的这个问题不错

http://stackoverflow.com/questions/5770032/cakephp-and-subquery

The Question:

How can I write SQL subquery using cake syntax. I know how to code simple query, but I can't handle subquery.

This is the original query:

1
2
3
4
5
6
7
8
SELECT Assumption.id, Referee.id, Referee.first_name, Referee.second_name
FROM referees AS Referee
INNER JOIN (
 
    SELECT a.id, a.referee_id
    FROM assumptions a
    WHERE a.season_id =7
) AS Assumption ON Referee.id = Assumption.referee_id

The answer

Since you didn't understand the syntax, this is the actual query:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$records = $this->Referee->find('all', array(
                'fields' => array(
                    'Assumption.id', 'Referee.id', 'Referee.first_name', 'Referee.second_name'
                    ),
                'joins' => array(
                    array(
                        'table' => 'assumptions',
                        'alias' => 'Assumption',
                        'type'  => 'INNER',
                        'foreignKey'    => false,
                        'conditions'    => array('Referee.id = Assumption.referee_id', 'Assumption.season_id = 7'),
                        ),
                ),
            )
        );

  Which produces this query:

1
2
3
4
5
6
7
8
9
SELECT
    `Assumption`.`id`,
    `Referee`.`id`,
    `Referee`.`first_name`,
    `Referee`.`second_name`
FROM `referees` AS `Referee`
INNER JOIN assumptions AS `Assumption`
    ON (`Referee`.`id` = `Assumption`.`referee_id`
        AND `Assumption`.`season_id` = 7)

  

Which provide the results you are looking for.

Sample output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Array
(
    [0] => Array
        (
            [Assumption] => Array
                (
                    [id] => 1
                    [0] => Array
                        (
                            [id] => 1
                            [season_id] => 7
                            [referee_id] => 1
                            [name] => SomeAssumpton
                        )
 
                )
 
            [Referee] => Array
                (
                    [id] => 1
                    [first_name] => Ref
                    [second_name] => one
                )
 
        )
 
)

  Another Answer

so after what seemed like years (several hours) and reading cake source... if you want to simply type your subquery into your cake conditions...

it uses php stdClass not an array entry... it will just dump your "value" into the query...

1
2
3
4
5
$subquery = new stdClass();
   $subquery->type = "expression";
   $subquery->value = "Product.id IN (select product_id from product_categories where category_id='$category_id' or belongs_to='$category_id')";
 
   $options['conditions'][] = $subquery;  <- dump the class into your conditions array!

  

do normal query $this->table->find('all', $options)

EXAMPLE: (normal cake with subquery quickfix)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//only from my vendor
    $options['conditions']['collection_id'] = $vendor_id;
 
    //inner join to CollectionProduct
    $options['joins'][0] = array(
        "table" => "collection_products",
        "alias" => "CollectionProduct",
        "type"  => "INNER",
        "conditions" => array(
            "Product.id = CollectionProduct.product_id",
        ),
    );
 
    //show only from current category
    if ($category_id) {
        $subquery = new stdClass();
        $subquery->type = "expression";
        $subquery->value = "Product.id IN (select product_id from product_categories where category_id='$category_id' or belongs_to='$category_id')";
        $options['conditions'][] = $subquery;
    } else {
        //get 18 random items... no category selected?
        $options['limit'] = 18;
    }
 
    return $this->find('all', $options);

  

 

1  
That's what happens behind the scenes, but the proper way to do it would be to follow the instructions in the Cookbook. –  Brad Koch Oct 7 '11 at 19:31
1  
if you goto your link and go down to "Sub-queries" you will see a huge overhead to generate the one line of sql shown above and this is short and sweet. there are plenty of queries cake "can't" do. If your doing multi-nested subqueries imagine how horrible the cookbook would be. –  duante Oct 7 '11 at 21:39
1  
The only reason this method saves space is because the subquery was written explicitly. The OP specifically stated they wanted to use cake methodology. The shortest route if you don't care is to simply use $this->Model->query(). Agreed, the guide's method is long, but it doesn't help that the author of the example code didn't do the greatest job. –  Brad Koch Oct 7 '11 at 21:55
1  
Only difference if you use query() directly you need to write the whole query not just an exception for the sub query. I have updated the example with an example to show this. –  duante 
posted @   立志做一个好的程序员  阅读(393)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现

不断学习创作,与自己快乐相处

点击右上角即可分享
微信分享提示