First of all, the staff you are going to do is not related to some specific user/group, so you need to create a static method, like this one:
public static function getSmallerGroups()
{
$criteria=new CDbCriteria;
$criteria->condition="id IN SELECT group_id FROM users WHERE COUNT(users.*)==MIN(users.*)";
return Group::model()->findAll($condition);
}
You can access this method as:
Groups::smallerGroups;
Also keep in mind that is possible to receive more than one "smaller" group.
This one’s possible, but tricky. I’d suggest trying to use a normal relation, but grouping and order the results by count. I’ve got to go to work, so haven’t tested this, but something along the lines of the following may work.
'leastUsers'=>array(self::HAS_ONE, 'Group', 'groupid',
'select'=>'Group.*, count(*) as users',
'join'=>'LEFT JOIN User ON User.groupid=Group.groupid'
'group'=>'Group.groupid',
'order'=>'users',
),
I expect that will fail, I think Yii would alias the table to something other than Group. Run the query in test mode so you can see the query generated in the log. Then, change the contents of the join, select, group statements to use the right table alias.
Remember, a relation generally returns a model. They generally give a model of the type given as the second parameter. If you’re having trouble figuring out how to do what you want as a relation, you might be better-off just writing a function to do a normal find. You can use Group::model->findAllBySql(‘SELECT Group.* …’) to run pretty-much any SQL search. If you don’t know how to do the search you want, there are plenty of guides on the internet for how to build SQL statements to do XYZ.
I tend to use a pure DAO solution in cases like this. All you want is an id, right? To get that you have to issue a simple SQL statement. There’s no requirement to stuff this into the “AR way of doing queries”:
public querySmallestGroup() {
$sql='SELECT g.id FROM Group g LEFT JOIN Users u ON g.id=u.groupid ORDER BY COUNT(g.id) DESC LIMIT 1';
return $this->db->createCommand($sql)->queryScalar();
}
This is easier, but what about if there are 2 empty group? Wich one will be returned? We should forseen that there is the possibility of more than one answer.
Pro tip: If you care about efficiency, never use “ORDER BY RANDOM()”. Even if you only need one result, ORDER BY RANDOM() will generate a random number for every table row. Generating a quasi-random number is actually fairly complex, I’d expect to see visible slowdown set in pretty quickly. You’d be much better is most cases to pull the whole set (or all groups with the minimum) and to select one from the list in PHP.