How to use yii2 joinWith aggregation (count, sum) query - yii2

I know use with query:
$customers = Customer::find()->with([
'country',
'orders' => function ($query) {
$query->andWhere(['status' => Order::STATUS_ACTIVE]);
},
])->all();
But, When I use count in with query, The result didn't contains aggregation column, Like that:
$query = UserInviteRecord::find()
->alias('ui')
->with([
'userInfo',
'inviteOrder' => function ($query) {
$query->select(['invite_user_id', 'count(id) as total_count']);
$query->where(['status' => 1]);
$query->groupBy('invite_user_id');
}])
->where(['ui.type' => 0])
Result only contains invite_user_id column.
replace select query:
$query->select(['invite_user_id', 'count(id) as total_count']);

Related

How do I order records not matched in leftJoin?

I'm new to Laravel and having a problem returning my results from this query in the correct order. I have a $products variable that contains both "A" and "B" type of products.
I'm doing a leftJoin with a match_products table to order the records by match_products.sku, but only "B" records are contained in that table.
$products = $products->with(['matches' => function ($quer) use ($business) {
$quer->where('user_id', $business->user_id)->with('skuDiscount');
}])->withCount(['variations' => function ($q) use ($business) {
$q->whereHas('seller_variations', function ($qu) use ($business) {
$qu->where('user_id', $business->user_id);
});
}])->leftJoin('match_products', function ($join) use ($business) {
$join->on('products.id', '=', 'match_products.product_id')
->where('match_products.user_id', '=', $business->user_id);
})
->orderBy('match_products.sku', $order)
->select('products.*')
->limit($perPage)
->offset($perPage * ($page - 1))
->get();
return response()->json(['products' => $products, 'productsCount' => $productsCount]);
My results are coming out:
A records
B records (in order by Sku)
but I need them to be the opposite:
B records (in order by Sku)
A records
I assume this is because the leftJoin is returning the matched records after the non-matched records but I need to return them before the non-matched records. I'd appreciate any help someone could please give me.

Laravel. How to get a record, that has all user ids in related table?

There is a chat table and intermediate table.
I need to get from the chat table only those chats for which all user identifiers are found.
Now I am getting records if at least one match is found
My query
$chat = $this->select('chats.*')->distinct()
->rightJoin("chat_user", function ($query) {
$query->on("chats.id", "=", "chat_user.chat_id")
->whereIn("chat_user.user_id", [2, 17]);
})
->where('chats.type', '=', 'single')
->get();
Result
But I need a chat width id 4, because only it matches my request
I also tried to do it like this
$chat = $this->select('chats.*')->distinct()
->rightJoin("chat_user", function ($query) use ($members_ids) {
$query->on("chats.id", "=", "chat_user.chat_id")
->where("chat_user.user_id", 2)
->where("chat_user.user_id", 17);
})
->where('chats.type', '=', 'single')->get();
But result is empty
In plain SQL, this could be achieved with the following query:
SELECT chats.*
FROM chats
WHERE chats.type = 'single'
AND EXISTS (SELECT 1 FROM chat_user WHERE user_id = 2 AND chat_id = chats.id)
AND EXISTS (SELECT 1 FROM chat_user WHERE user_id = 7 AND chat_id = chats.id)
Translated into a Laravel query, we get the following:
$userIds = [2, 7];
$chats = DB::table('chats')
->where('chats.type', 'single')
->where(function (Builder $query) use ($userIds) {
foreach ($userIds as $userId) {
$query->whereExists(fn (Builder $query) => $query
->select(DB::raw(1))
->from('chat_user')
->where('chat_user.user_id', $userId)
->whereColumn('chat_user.chat_id', 'chats.id'));
}
})
->select('chats.*')
->get();
You should do something like this instead:
$chat = $this->select('chats.*')->distinct()
->rightJoin('chat_user', function ($query) {
$query->on('chats.id', '=', 'chat_user.chat_id')
->where('chat_user.user_id', 2)
->where('chat_user.user_id', 17);
})
->where('chats.type', '=', 'single')
->get();
Specifying multiple where works as an AND condition. If you use whereIn() will work as an OR conditions for the supplied values.

MySql group by with where condition not working

I have 2 tables, groups and questions. I need the result in such a way that it contains group name and corresponding non-deleted question count.
The structure and data for the two tables are as afollows.
My expected Result is as follows
I tried the following code, but it gives the entire row including the deleted questions.
$groupname = DB::table('groups as d')
->select([
'd.id','d.group_name',DB::raw("count(dtls.survey_group_id) as count")
])
->leftJoin('questions as dtls','d.id', '=', 'dtls.survey_group_id')
->whereNotExists( function ($query) {
$query->select(DB::raw(1))
->from('questions')
->where('id', 'd.id')
->where('dtls.is_deleted', 1);
})
->groupBy('d.id','d.group_name')
->get()
->toArray();
A problem here is that ->where('id', 'd.id') mathches id with the literal string d.id which obviously is not what you want. In addition, inner query tables should be aliased to prevent ambiguity. You can try changing it to:
$groupname = DB::table('groups as d')
->select([
'd.id','d.group_name',DB::raw("count(dtls.survey_group_id) as count")
])
->leftJoin('questions as dtls','d.id', '=', 'dtls.survey_group_id')
->whereNotExists( function ($query) {
$query->select(DB::raw(1))
->from('questions as innerDtls')
->whereRaw('innerDtls.id = d.id')
->where('dtls.is_deleted', 1);
})
->groupBy('d.id','d.group_name')
->get()
->toArray();
Alternatively your current query can be simplified to:
$groupname = DB::table('groups as d')
->select([
'd.id','d.group_name',DB::raw("count(dtls.survey_group_id) as count")
])
->leftJoin('questions as dtls','d.id', '=', 'dtls.survey_group_id')
->where('dtls.is_deleted', 0)
->groupBy('d.id','d.group_name')
->get()
->toArray();

Laravel Eloquent orWhere issues

Been wandering what's wrong with my query should be as easy as it seems.
its more like i'm creating a select * from table where (a = 1 and b =2)
or (a = 2 and b = 1) type of query. Here's my eloquent.
return $query->where(function($q) use ($brand, $influencer, $agency){
$q->where([
'sender_id' => $brand,
'receiver_id' => $influencer
]);
$q->orWhere([
'sender_id' => $influencer,
'receiver_id' => $brand
]);
});
I have this query in my eloquent but when display in debug bar it's showing
select count(*) as aggregate
from `chat_messages`
where ((`sender_id` = '415' and `receiver_id` = '1159')
or (`sender_id` = '1159' or `receiver_id` = '415'))
and i wanted it to be "AND" inside the second parenthesis group
select count(*) as aggregate
from `chat_messages`
where ((`sender_id` = '415' and `receiver_id` = '1159')
or (`sender_id` = '1159' AND `receiver_id` = '415'))
If you call orWhere() with an array, it uses OR in front and between the individual constraints.
Use this:
return $query->where(function($q) use ($brand, $influencer, $agency){
$q->where([
'sender_id' => $brand,
'receiver_id' => $influencer
])->orWhere(function($q) use ($brand, $influencer) {
$q->where([
'sender_id' => $influencer,
'receiver_id' => $brand
]);
});
});

CakePHP 3: How to count and retrieve data for different periods in one query?

I want to count and retrieve data for different periods like today, total, this week, etc by DATETIME created field.
How to count for example this_week?
Here is starting code:
public function findTotalRegistered(Query $query, Array $options)
{
$total = $query->func()->count('id');
$query
->select([
'total' => $total,
//'today' => $today,
//'this_week' => $this_week,
//'this_month' => $this_month,
//'this_year' => $this_year
]);
return $query;
}
You can achieve this by doing sub-query:
public function findTotalRegistered(Query $query, Array $options)
{
$total = $query->func()->count('id');
$query
->select([
'total' => $total,
'today' => $query->where('DATE(created) = CURDATE()')->count(),
'this_week' => $query->where('YEARWEEK(DATE(created), 1) = YEARWEEK(CURDATE(), 1))')->count(),
'this_month' => $query->where('DATE_SUB(NOW(), INTERVAL 1 MONTH)')->count(),
'this_year' => $query->where('YEAR(created) = YEAR(CURDATE())')->count()
])
->group(created);
return $query;
}
Thanks