How to get row count using laravel fluent query builder - mysql

How to get the row count using Laravel fluent query builder
I have attached the query I used to filter other data and also I need to get the row count.
Here is the database Table:-
$results = DB::table('newsfeed_posts')
->select('newsfeed_posts.*', 'users.first_name as posted_user_first_name', 'users.last_name as posted_user_last_name', 'users.profile_image as posted_user_profile_image','proid.profile_image as posted_receiver_profile_image', 'timeline.first_name as post_receiver_first_name', 'timeline.last_name as post_receiver_last_name', 'timeline.office_branch_id as post_receiver_office_id')
->leftJoin('users', 'users.id', 'newsfeed_posts.post_sender_id')
->leftJoin('users as timeline', 'timeline.id', 'newsfeed_posts.post_receiver_id')
->leftJoin('users as proid', 'proid.id', 'newsfeed_posts.post_receiver_id')
->where('newsfeed_posts.deleted_status', '0')
// ->where('newsfeed_posts.post_sender_id', Auth::user()->id)
->where('newsfeed_posts.post_receiver_id', Auth::user()->id)
->groupBy('newsfeed_posts.id')
->orderBy('newsfeed_posts.id', 'DESC')
->get();
return $results;

Using pure Laravel query builder, you may have to issue two separate queries:
$count = DB::table('newsfeed_posts')
->select('newsfeed_posts.*', 'users.first_name as posted_user_first_name', 'users.last_name as posted_user_last_name', 'users.profile_image as posted_user_profile_image','proid.profile_image as posted_receiver_profile_image', 'timeline.first_name as post_receiver_first_name', 'timeline.last_name as post_receiver_last_name', 'timeline.office_branch_id as post_receiver_office_id')
->leftJoin('users', 'users.id', 'newsfeed_posts.post_sender_id')
->leftJoin('users as timeline', 'timeline.id', 'newsfeed_posts.post_receiver_id')
->leftJoin('users as proid', 'proid.id', 'newsfeed_posts.post_receiver_id')
->where('newsfeed_posts.deleted_status', '0')
->where('newsfeed_posts.post_receiver_id', Auth::user()->id)
->groupBy('newsfeed_posts.id')
->count();
Then, use your current query to generate the result set you want.
If you are using MySQL 8+ under the hood, then there is an alternative. We can try using COUNT() as an analytic function, using just a single query:
$results = DB::table('newsfeed_posts')
->selectRaw('COUNT(*) OVER () AS cnt, newsfeed_posts.*', 'users.first_name as posted_user_first_name', 'users.last_name as posted_user_last_name', 'users.profile_image as posted_user_profile_image','proid.profile_image as posted_receiver_profile_image', 'timeline.first_name as post_receiver_first_name', 'timeline.last_name as post_receiver_last_name', 'timeline.office_branch_id as post_receiver_office_id')
->leftJoin('users', 'users.id', 'newsfeed_posts.post_sender_id')
->leftJoin('users as timeline', 'timeline.id', 'newsfeed_posts.post_receiver_id')
->leftJoin('users as proid', 'proid.id', 'newsfeed_posts.post_receiver_id')
->where('newsfeed_posts.deleted_status', '0')
->where('newsfeed_posts.post_receiver_id', Auth::user()->id)
->groupBy('newsfeed_posts.id')
->orderBy('newsfeed_posts.id', 'DESC')
->get();
The count over the entire result set (after GROUP BY aggregation) would then be available using the alias cnt.

If you want to get all the filtered records from database with number of fetched items record. Then you can use firstly use get all results using get() function and on this result you can use ->count() to get all fetched items count.
$result = DB::table('newsfeed_posts')
->select('newsfeed_posts.*', 'users.first_name as posted_user_first_name', 'users.last_name as posted_user_last_name', 'users.profile_image as posted_user_profile_image','proid.profile_image as posted_receiver_profile_image', 'timeline.first_name as post_receiver_first_name', 'timeline.last_name as post_receiver_last_name', 'timeline.office_branch_id as post_receiver_office_id')
->leftJoin('users', 'users.id', 'newsfeed_posts.post_sender_id')
->leftJoin('users as timeline', 'timeline.id', 'newsfeed_posts.post_receiver_id')
->leftJoin('users as proid', 'proid.id', 'newsfeed_posts.post_receiver_id')
->where('newsfeed_posts.deleted_status', '0')
// ->where('newsfeed_posts.post_sender_id', Auth::user()->id)
->where('newsfeed_posts.post_receiver_id', Auth::user()->id)
->groupBy('newsfeed_posts.id')
->orderBy('newsfeed_posts.id', 'DESC')
->get();
return [
'total' => $result->count(),
'result' => $result
];

Related

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();

How to get total users average time passed 7 days

I want to get the per day total users average usage time for passed 7 days i written the the SQL for each users average time it's coming perfectly but i have an u\issues in LARAVEL SQL function please help fix this SQL.
$currentTime = Carbon::today();
$userUsage = DB::table('active_user')
->select(DB::raw('acu_name as name'),
DB::raw('u_fname as fname'),
DB::raw('AVG(TIMESTAMPDIFF(MINUTE,acu_at,acu_et)) as averageTime'),
DB::raw('count(*) as number'))
->join('u_info_one', 'active_user.acu_name', '=', 'u_info_one.u_email')
->whereDate('acu_at', '<=', $currentTime)
->groupBy('acu_name')
->get();
You need to use GROUP BY for this, e.g.:
$userUsage = DB::table('active_user')
->select(DB::raw('acu_name as name'),
DB::raw('u_fname as fname'),
DB::raw('AVG(TIMESTAMPDIFF(MINUTE,acu_at,acu_et)) as averageTime'),
DB::raw('count(*) as number'))
->join('u_info_one', 'active_user.acu_name', '=', 'u_info_one.u_email')
->whereDate('acu_at', '<=', $currentTime)
->groupBy('acu_name', DB::raw('DATE(acu_at)'))
->get();
update
If you just need daily average for all the users, you can remove acu_name from group by, e.g.:
$userUsage = DB::table('active_user')
->select(DB::raw('acu_name as name'),
DB::raw('u_fname as fname'),
DB::raw('AVG(TIMESTAMPDIFF(MINUTE,acu_at,acu_et)) as averageTime'),
DB::raw('count(*) as number'))
->join('u_info_one', 'active_user.acu_name', '=', 'u_info_one.u_email')
->whereDate('acu_at', '<=', $currentTime)
->groupBy(DB::raw('DATE(acu_at)'))
->get();
Correct Answer is
$userUsage = DB::table('active_user')
->select(DB::raw('DATE(acu_at) as date'),
DB::raw('AVG(TIMESTAMPDIFF(MINUTE,acu_at,acu_et)) as averageTime'),
DB::raw('COUNT(DISTINCT `acu_name`) as users'))
->join('u_info_one', 'active_user.acu_name', '=', 'u_info_one.u_email')
->whereDate('acu_at', '<=', $currentTime)
->groupBy(DB::raw('DATE(acu_at)'))
->orderBy(DB::raw('DATE(acu_at)'))
->get();
foreach($userUsage as $usUa)
{
$avegTime = ($usUa->averageTime/$usUa->users);
echo "['".$usUa->date."',".$avegTime."],";
}

Laravel count with where on Query Builder with joins

Good day all, I am trying to count all records in a table but only if the table does not contain data in a specific column (deleted_at). It is a join table the table names are companies and employees. I am currently counting the records with a DB::raw but it should only count it if the deleted_at column is null. Please understand that i am a beginner.
public function index()
{
$user = Auth::user()->id;
$companies = DB::table('companies AS c')
->select([
'c.id',
'c.logo',
'c.company_name',
'c.created_at',
'c.sector',
'c.deleted_at',
DB::raw('COUNT(e.id) AS employee_count')
])
->leftJoin('employees AS e', 'e.company_id', '=', 'c.id' )
->leftJoin('company_user AS cu', 'cu.company_id', '=', 'c.id')
->where('cu.user_id', '=', $user)
->where('c.deleted_at', '=', null)
->groupBy('c.id')
->get();
return view('account.companies.index')
->with('companies', $companies);
}
If you are using Mysql then you could use conditional aggregation
$companies = DB::table('companies AS c')
->select([
'c.id',
'c.logo',
'c.company_name',
'c.created_at',
'c.sector',
'c.deleted_at',
DB::raw('SUM(c.deleted_at IS NULL) AS employee_count')
])
->leftJoin('employees AS e', 'e.company_id', '=', 'c.id' )
->leftJoin('company_user AS cu', 'cu.company_id', '=', 'c.id')
->where('cu.user_id', '=', $user)
->groupBy('c.id')
->get();
In mysql when an expression is used inside sum(a= b) it will result as a boolean 0/1 so you can get your conditional count using above
Or you could use whereNull() method in your query
->whereNull('c.deleted_at')
Use this code:
$employeeCount = DB::table('employees')
->select('companies.name', DB::raw('count(employees.id) as employee_count'))
->join('companies', 'employees.company','=','companies.id')
->groupBy('companies.id')
->get();

Join the same table with two different column laravel

I try these code in MySQl:
SELECT
A.*,
B.name,
C.name
FROM
eventlog_tbl as A
LEFT JOIN users B ON A.byuser=B.email
LEFT JOIN users C ON A.affectiveuser=C.email;
I try these in Laravel
return DB::table('eventlog_tbl')
->leftjoin('users', 'users.email', '=', 'eventlog_tbl.byuser')
->leftjoin('users', 'users.email', '=', 'eventlog_tbl.affectiveuser')
->select('eventlog_tbl.*','users.name','users.name')
->get();
How can i convert it to Laravel?
Try below code:
$res = DB::table('eventlog_tbl')
->leftjoin('users AS A', 'A.email', '=', 'eventlog_tbl.byuser')
->leftjoin('users AS B', 'B.email', '=', 'eventlog_tbl.affectiveuser')
->select('eventlog_tbl.*','A.name as byuser_name','B.name as affectiveuser_name')
->get();
print_r($res);
This is your query written using the Laravel query builder.
$events = DB::table('eventlog_tbl')
->select('eventlog_tbl.*', 'users_1.name', 'users_2.name')
->leftJoin('users AS users_1', 'users_1.email', '=', 'eventlog_tbl.byuser')
->leftJoin('users AS users_2', 'users_2.email', '=', 'eventlog_tbl.affectiveuser')
->get();
Edit:
$events = DB::table('eventlog_tbl')
->select('eventlog_tbl.*', 'users_1.name AS user_1', 'users_2.name AS user_2')
->leftJoin('users AS users_1', 'users_1.email', '=', 'eventlog_tbl.byuser')
->leftJoin('users AS users_2', 'users_2.email', '=', 'eventlog_tbl.affectiveuser')
->get();
The problem is that both name columns are called the same thing. As per the accepted answer, these will need to be aliased differently too.
Why don't you convert this to use relationships? I have probably got the relationships wrong, something like this:
class EventLog extends Model
{
public function byUser()
{
return $this->hasOne(User::class, 'byuser', 'id');
}
public function affectiveUser()
{
return $this->hasOne(User::class, 'affectiveuser', 'id');
}
}
And then
$event_log = EventLog::with(['byUser', 'affectiveUser')->all();
foreach ($event_log as $item) {
echo $item->byUser->email();
}

Where clause on join query laravel 4.2

I have 2 tables 'users' and 'instantUsers'. I want to join them on users.id = instantUsers.user_id and want to add 2 where clauses on the resulting. I'm not getting how to do both. The query I'm using is -
DB::table('users')
->join('instantUsers', function($join) use ($userId) {
$join->on('users.id', '=', 'instantUsers.user_id');
})
->where('instantUsers.instantMode', '=', '1')
->where (function($query) use ($userId) {
$query->where('instantUsers.user_id', '!=', $userId);
})
->get();
You can try this one maybe this will help you:
DB::table('users as table1')->join('instantUsers as table2','table1.id','=','table2.fkId') ->where('table2.instantMode','=','1')->where('table2.user_id','!=',$userId)->get();
Your 'instantUsers.instantMode','=','1' expression can be done in a join, resulting in a better performance.
I would write it like this
DB::table('users')
->join('instantUsers', function($join) use ($userId) {
$join
->on('users.id', '=', 'instantUsers.user_id')
->on('instantUsers.instantMode', '=', 1);
})
->where('users.id', '!=', $userId)
->get();