GROUP and COUNT() ages in CakePHP

后端 未结 4 1093
悲&欢浪女
悲&欢浪女 2021-01-05 19:34

I\'m trying to group by date of birth and count based on the results, using CakePHP. Here\'s my query.

$data = $this->User->find(\'all\', array(
    \         


        
相关标签:
4条回答
  • 2021-01-05 19:43

    First, I don't think you need 'COUNT(id)'. You can always count that in PHP easily:

    foreach($data as $group){echo count($group);}
    

    To filter, check on the original field, not the derived one:

    'conditions'=>array('User.dob >' => date('Y-m-d', strtotime('-20 years')))
    

    Anyhow, there's always Model->query() if you need.

    0 讨论(0)
  • 2021-01-05 19:58

    The results you get are pretty much the best that CakePHP produces.

    To simplify this you should use Set::combine which re-indexes your array.

    You would need to call $data = Set::combine($data, '{n}.0.age', '{n}.0.COUNT(id)');

    This would return an array with age as the index and count as the value:

    Array
    (
        [9] => Array
            (
                [COUNT(id)] => 1
    
            )
    
        [10] => Array
            (
                [COUNT(id)] => 1
    
            )
        ...
    )
    

    The reason for the extra depth in the array is that cake uses the model as the key for the inner array if you are not using calculated fields, so that you can put in multiple models as fields and they will be split into different arrays. When you use calculated fields it keeps the same structure, but doesn't know the model so has to put it in a general array.

    So lets say you want to group by male/female as well and you have a User.sex field, which is not a calculated field.

    $data = $this->User->find('all', array(
        'fields' => array(
            "User.sex"
            "DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(User.dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(User.dob, '00-%m-%d')) AS age",
            'COUNT(User.id) AS [count]' // n.b. you have to give aliases normally
        ),
        'group' => 'age', 'User.sex'
    ));
    

    This would return (something like):

    Array
    (
        [0] => Array
            (
                [User] => Array
                    (
                        [sex] => Male
                    )
                [0] => Array
                    (
                        [age] => 4
                        [count] => 1
                    )
    
            )
    
        [1] => Array
            (
                [User] => Array
                    (
                        [sex] => Female
                    )
                [0] => Array
                    (
                        [age] => 10
                        [count] => 1
                    )
    
            )
    
        [2] => Array
            (
                [User] => Array
                    (
                        [sex] => Male
                    )
                [0] => Array
                    (
                        [age] => 10
                        [count] => 1
                    )
    
            )
    )
    

    Thus for consistency the extra depth is always there even if you only use calculated fields

    0 讨论(0)
  • 2021-01-05 19:58

    I think you are getting numeric indexes on your results array because the fields you are adding haven't been generated by CakePHP. CakePHP usually generates queries (and field names) more like this in SQL:

    SELECT `Item`.`id`, `Item`.`name` FROM `items` AS `Item` WHERE 1 = 1 ORDER BY `Item`.`name` ASC
    

    You should try and mimic CakePHP's field naming conventions when adding custom elements to your queries, if you want CakePHP to better understand and format the results coming back from MySQL:

    $age = "DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(User.dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(User.dob, '00-%m-%d'))";
    $data = $this->User->find('all', array(
        'conditions' => array('User.age >' => 20),
        'fields' => array(
            $age . ' AS `User`.`age`',
            'COUNT(id) AS `User`.`count`'
        ),
        'group' => 'User.age'
    ));
    

    Maybe this will give you more luck getting the conditions to work. :)

    0 讨论(0)
  • 2021-01-05 20:02

    What version of cakephp are you using? I think earlier versions of 1.2 and I believe all versions of 1.1 had some issues with group by and complex aggregate queries -- it was later resolved. That said the results look like cake is running what you are asking it to: returning a list of the ages, and the count of the users with that age.

    Regardless, why run that in mysql and tie up your db server? Get the raw values, and rewrite the query to calculate the aggregates in php, and append it to the returned array.

    If you must use mysql, there is always $this->query(); For complex queries its often worth it to bypass cake, but as I said, the results make sense given the query.

    0 讨论(0)
提交回复
热议问题