-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How create statistical query in relation? #2179
Comments
class Customer extends \yii\db\ActiveRecord
{
public function getOrderCount()
{
// Customer has_many Order via Order.customer_id -> id
return $this->hasMany(Order::className(), ['customer_id' => 'id'])->count();
}
} $orderCount = Customer::find(['id' => 10])->getOrderCount(); |
Да я понимаю, что так можно. Сейчас если написать так: $customers = Customer::find()->with('orders')->all(); Получим следующие sql запросы: SELECT * FROM tbl_customer LIMIT 100;
SELECT * FROM tbl_orders WHERE customer_id IN (1,2,...) Хотелось бы что то подобное. Пока смотрел возможности родился такой вариант: public function getClientCount()
{
$relation = $this->hasOne(Client::className(), ['insurance_id' => 'id']);
$relation->select = "COUNT(*) as `count`, `insurance_id`";
$relation->groupBy(['insurance_id']);
$relation->asArray();
return $relation;
} Но как то не очень выглядит и в сlientCount получаем массив, а не само значение. |
bump, @qiangxue what your thoughts about this one? |
So this is basically about eager loading for statistical queries? |
yes |
set for RC, will think about it. |
this one goes up. is it time to implement it? I see that it is scheduled to |
@Ragazzo any suggestions? Just saying to hurry does not help anything to make progress here ;) |
naah, was not looking for internals of AR, maybe if i will have time, but not sure about it ) Sorry if offended you, was not upping this issue for offense, only for notice that this is a very useful enh and is at the bottom of all issues , because it was created long time ago ) |
@Ragazzo milestone is RC so we agree that it's important enough. |
I need to bring back all Customers with Order count > 0 Is this the same issue? |
@nsanden not at all. You want instances of customer, here we are talking about stat relations. Depending on your schema you might get that by just LEFT JOINing the order table... |
Thanks @cebe, always helpful. I was able to finally pull it off doing something like this: $query = Customer::find();
$query->select("tbl_customer.*, COUNT(tbl_order.id) AS order_count");
$query->leftJoin('tbl_order', 'tbl_order.customer_id = tbl_customer.id');
$query->groupBy(['tbl_customer.id']);
$query->having("COUNT(tbl_order.id) > 0");
$dataProvider = new ActiveDataProvider([
'query' => $query,
]); then in model public function attributes()
{
// add related fields to searchable attributes
return array_merge(parent::attributes(), ['tbl_customer.order_count']);
} seems kind of hacky, am i going about it the wrong way? |
@nsanden this is completely offtopic and not a bug report, please create a topic in the forum instead. |
Milestone set for 2.0.1, can be in 2.0 if someone is making a pull request. |
This requires some significant work. Move to 2.1. |
Now, what is the best solution to get count from relation and a sortable column in gridview!? |
EDIT: nope, it does not, sry :) |
My approach for getting statistic: class DealerReport extends Dealer
{
public static function find()
{
$query = parent::find();
$query->select([
'dealers.*',
'managers.users_count as managers_count',
'leaders.users_count as leaders_count',
]);
$query->from([
'dealers' => Dealer::tableName(),
]);
$query->leftJoin([
'managers' => User::find()->select('dealer_id, COUNT(*) as users_count')->where(['role' => User::ROLE_SALES])->groupBy(['dealer_id'])
], 'managers.dealer_id = dealers.id');
$query->leftJoin([
'leaders' => User::find()->select('dealer_id, COUNT(*) as users_count')->where(['role' => User::ROLE_DEALER])->groupBy(['dealer_id'])
], 'leaders.dealer_id = dealers.id');
return $query;
}
public function attributeLabels()
{
return array_merge(parent::attributeLabels(), [
'managers_count' => 'Number of managers',
'leaders_count' => 'Number of leaders'
]);
}
public function attributes()
{
return array_merge(parent::attributes(), [
'managers_count', 'leaders_count'
]);
}
} In this example each dealer has plenty on users, some of them are leaders (ROLE_LEADER), other - simple managers (ROLE_SALES). Subqueries used here gives ability to deal with multiple stat requests at one time |
Issue is outdated. |
@klimov-paul I cannot see how does yii\db\ActiveQuery::joinWith() solves the problem of eager loading for scalar/aggregate values. It works only with related objects. I wouldn't mind implementing statistical relation handling at application level (if you think it adds too much complexity to the framework code), but it seems that the way ActiveRecord and ActiveQuery currently works makes this task a very difficult one. Please either add a few lines abut this topic to the guide (if you have a working and relatively easy-to-implement solution) or reopen the issue. |
There is no way get statistical data, except of composing complex SQL for that. Customer::find()->joinWith('posts')->addSelect('COUNT(posts.id) AS postCount')->groupBy('t.id')->all(); All you need is reserve a public field You may override class CustomerQuery extends ActiveQuery
{
public function withPostsCount()
{
$this->joinWith('posts')->addSelect('COUNT(posts.id) AS postCount')->groupBy('t.id');
}
} Such approach is already described at the docs. You are asking about statistical query, because back in Yii1 we have a special relation for that, and now we have not. I inderstand this is quite a sad thing to realize, but it is as it is. Still, if anyone of @yiisoft/core-developers think this issue requires further threatment like docs updating or anything else - feel free to reopen it. |
Added extra docs 13b10bd |
i think need:
problem now, that relation valid is instance of ActiveRelation, but queryScalar return integer example: and in findFor run $relation->queryScalar(/more info here/) |
@lynicidn your suggestion is about retrieving single column of the existed model instead if the hole model instead. This is not what statistical relations are about. Generally we have to calculate some values in runtime using sql and attach this values to the original model. And this is not really the relation. |
@omnilight i don't understand u, sry, but any join relation it relation, aggregate or not it relation! |
Couldn't my virtual fields proposal solve this? |
Not sure if something changed since, but I tried following #2179 (comment) and the call
This worked instead:
|
@vercotux I think joinWith does not necessarily do a join query. Instead you should use "innerJoinWith" or one of the others. |
I too strived to make all this work.. ..but finally succeeded in showing in GridView the count of the number of License(s) owned by a User2016.
The License model has a relation with the User2016.. ..but it is not involved in solving the specific case. Inside the UserController, in the actionIndex() function, I define the $dataProvider:
Finally.. ..in the view, I add the GridView:
|
When I want one more count value, try to join anather table like below, but it not work: |
Если вы хотите чтобы поиск и сортировка по количество свзязанных таблиц была быстрой, Для уверенности в том что данные актуальны, можно создать какое не будь представление в БД..., к архетектуре которой вас могут не пустить). При подсчете количество нескольких связей по LEFT JOIN, результат выходит не корректным. Как вариант можно использовать вот такой код в модели для Поиска. Метод search в модели поиска:
Результат:
|
I have this working for both eager and lazy loading. It supports any type of relationship using subquery in the select. This allows for a clean implementation. |
I have table car carry, and model car model has one car carry. Model car has one car model. |
Thank you for your question. We advise you to use our community driven resources: If you are confident that there is a bug in the framework, feel free to provide information on how to reproduce it. This issue will be closed for now. This is an automated comment, triggered by adding the label |
How create statistical query in relation?
In Yii1:
The text was updated successfully, but these errors were encountered: