Laravel Database MySQL Queries take very long - mysql

I have a page that connects to my database, but it takes about 1 minute for the page to load after collecting all the data.
Is there something I am doing wrong, or is there something I can do to speed this process up?
Controller
class ReportSummaryController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function __construct()
{
$this->middleware('auth');
$user = Auth::user();
if (#$user->name)
$details = DB::table('taffiliate')
->where('affID', "=", $user->name)
->get();
else
return redirect('/login');
view()->share('details', $details);
}
public function index()
{
$user = Auth::user();
$affiliate = $user->name;
$affdata = DB::table('toutcome')->select(DB::raw('sum(LenderCommission) as LenderCommission'), 'AffID', 'AppID')
->whereRaw('CompletedDate >= curdate()')
->groupBy('AffID')
->orderBy('AppID', 'ASC')
->get();
$data3 = DB::table('toutcome')
->where('CompletedDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->whereRaw('AffID Not Like "MW0050"')
->join('tapplicant', 'toutcome.AppID', '=', 'tapplicant.AppID')
->select(DB::raw('DATE_FORMAT(CompletedDate, "%d %M %Y") as CompletedDate,
SUM(LenderCommission) as commission,
SUM(AffCommission) as affCommission,
COUNT(DISTINCT tapplicant.Email) as leadcount,
SUM(Status = "A" AND LenderCommission Not Like "0.00") as acceptcount'))
->groupBy(DB::raw('DATE_FORMAT(CompletedDate, "%d %M %Y")'))
->get();
$users = Toutcome::where('CompletedDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->join('tapplicant', 'toutcome.AppID', '=', 'tapplicant.AppID')
->select(DB::raw('DATE_FORMAT(CompletedDate, "%d %M %Y") as CompletedDate,
SUM(LenderCommission) as Commission,
SUM(AffCommission) as Affiliate_Commission,
COUNT(DISTINCT tapplicant.Email) as Applications,
SUM(Status = "A" AND LenderCommission Not Like "0.00") as Sold'))
->whereRaw('AffID Not Like "MW0050"')
->groupBy(DB::raw('DATE_FORMAT(CompletedDate, "%d %M %Y")'))
->get();
$comtotal = DB::table('toutcome')
->where('CompletedDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->whereRaw('LenderCommission Not Like "0.00"')
->sum('LenderCommission');
$subid = DB::table('tapplicant')
->whereRaw('AppAffID Not Like "050"')
->whereRaw('AppAffID Not Like "000"')
->where('AppDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->select('AppAffID')
->groupBy('AppAffID')
->get();
$lender = DB::table('toutcome')
->select('LenderName')
->groupBy('LenderName')
->get();
$imtotal = DB::table('toutcome')
->where('CompletedDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->whereRaw('LenderCommission Not Like "0.00"')
->whereRaw('AffID Not Like "0050"')
->count('AppID');
$cototal = DB::table('toutcome')
->where('CompletedDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->whereRaw('LenderCommission Not Like "0.00"')
->whereRaw('AffID Not Like "0050"')
->where('Status', '=', 'A')
->count('AppID');
$comtotal2 = DB::table('toutcome')
->where('CompletedDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->whereRaw('LenderCommission Not Like "0.00"')
->sum('LenderCommission');
$comtotal3 = DB::table('toutcome')
->where('CompletedDate', '>=', \Carbon\Carbon::now()->startOfMonth())
->whereRaw('LenderCommission Not Like "0.00"')
->sum('AffCommission');
return view('summary', compact('affdata','data3', 'comtotal', 'subid' , 'users', 'lender', 'imtotal', 'cototal', 'comtotal2', 'comtotal3'));
}

Firstly that sounds really long.
The queries do look quite detailed, but it shouldn't take longer than 1 minute.
You could try using eloquent, but this will be only a little quicker than the raw queries.
Things you didn't mention are :
Is this a local server or remote server ?
If you are using a remote server, my solution would be to use the "skip-name-resolve" in your my.ini / my.cnf under mysqld and update your key_buffer_size.
If this does not improve the speed, maybe look at your resources for that particular server.

Related

Laravel subquery in from clause

I need to use subquery in from clause but i can not find such thing in Laravel docs
Laravel version 5.4
$sub = Chat::join("chats as _chats", function ($query) {
$query->on('chats.room_id', "=", "_chats.room_id")
->on('chats.user_type', "<>", "_chats.user_type")
->on('chats.created_at', "=", DB::raw("(SELECT MIN(created_at) FROM chats WHERE created_at > '_chats.created_at')"));
})
->selectRaw('TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res')
->where('chats.user_type', 'pharmacy_consultant')
->where('chats.user_id', 26)
->toSql();
dd(
DB::connection('mysql2')
->table(DB::raw("({$sub}) as sub"))
->select('res')
->get()
);
(2/2) QueryException SQLSTATE[HY000]: General error: 2031
(SQL: select `res` from (select TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res
from `chats` inner join `chats` as `_chats` on `chats`.`room_id` = `_chats`.`room_id` and `chats`.`user_type` <> `_chats`.`user_type` and `chats`.`created_at` =
(SELECT MIN(created_at) FROM chats WHERE created_at > _chats.created_at) where `chats`.`user_type` = ? and `chats`.`user_id` = ?) as sub)
Try passing the builder instance instead of the raw query.
// $sub = Query Builder instance
$sub = Chat::join("chats as _chats", function ($query) {
$query->on('chats.room_id', "=", "_chats.room_id")
->on('chats.user_type', "<>", "_chats.user_type")
->on('chats.created_at', "=", DB::raw("(SELECT MIN(created_at) FROM chats WHERE created_at > '_chats.created_at')"));
})
->selectRaw('TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res')
->where('chats.user_type', 'pharmacy_consultant')
->where('chats.user_id', 26);
// ->toSql();
DB::connection('mysql2')
->table($sub, "sub")
->select('res')
->get()
Since you're not doing anything else than a select in your final query, why not just do that in the first query instead?
$results = Chat::join("chats as _chats", function ($query) {
$query->on('chats.room_id', "=", "_chats.room_id")
->on('chats.user_type', "<>", "_chats.user_type")
->on('chats.created_at', "=", DB::raw("(SELECT MIN(created_at) FROM chats WHERE created_at > '_chats.created_at')"));
})
->selectRaw('TIMESTAMPDIFF(MINUTE, _chats.created_at, chats.created_at) as res')
->where('chats.user_type', 'pharmacy_consultant')
->where('chats.user_id', 26)
->select('res')
->get();
Make it fit to your needs:
...
->addSelect([res' => ChartModel::select('//whatever')
->whereColumn('//sub-query column', 'parent-table.field')
->whereColumn('//and whatever')
->latest()
->take(1)
)]
...

MySQL date in between month and year

How to query date month and year between from_date and to_date?
What I tired:
$posts = my_table::whereYear('from_date', '>=', $year)
->whereMonth('from_date', '>=', $month)
->whereYear('to_date', '<=', $year)
->whereMonth('to_date', '<=', $month)
->get();
Query I want to execute:
SELECT * FROM my_table
WHERE (MONTH(from_date)>=2 AND (Year(from_date)>=2019)
AND (MONTH(to_date)=<4 AND (Year(to_date)=<2019)
I think this is what you might be looking for:
$posts = my_table::whereRaw("(MONTH('from_date') > 2 AND YEAR('from_date') >= 2019)")
->whereRaw("(MONTH('to_date') < 4 AND YEAR('to_date') <= 2019)")
->get();
Here's an example.
You can use the eloquent method too.
$result = my_table::where(function($query){
$query->where(DB::raw('MONTH(from_date)'), '>=' , 2)
->where(DB::raw('Year(from_date)'), '>=' , 2019);
})
->where(function($query){
$query->where(DB::raw('MONTH(to_date)'), '<=' , 4)
->where(DB::raw('YEAR(to_date)'), '<=' , 2019);
})
->get();
you may also do it in this way.
return Post::whereRaw("STR_TO_DATE('from_date', '%M%Y') > STR_TO_DATE('022019', '%M%Y')")
->whereRaw("STR_TO_DATE('from_date', '%M%Y') < STR_TO_DATE('042019', '%M%Y')")
->get();

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

How can I use 'AS' in my count query?

How can I use AS in my count query?
Actually i want to result like { "count":"number" } for json result. I dont know what should i call this thing?
public function firstHourTrades(){
$user_id = Auth::user()->id;
$data = DB::table('finaltrade')
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->where('finaltrade.user_id', $user_id)
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '>=', DB::raw('exchanges.start_time'))
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '<=', DB::raw("ADDTIME(exchanges.start_time, '1:00:00')"))
->count();
return response()->json($data);
}
You could also do a raw select and manually assign the alias:
$data = DB::table('finaltrade')
->select(DB::raw('count(*) as count'))
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->where('finaltrade.user_id', $user_id)
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '>=', DB::raw('exchanges.start_time'))
->whereTime(DB::raw('IF(finaltrade.buy_datetime<finaltrade.sell_datetime, finaltrade.buy_datetime, finaltrade.sell_datetime) '), '<=', DB::raw("ADDTIME(exchanges.start_time, '1:00:00')"))
->get();

CURDATE() with laravel 5

I'm new to laravel and i am wanting to use multiple where clauses and use curdate().
This is an example :
$data = DB::table('toutcome')->where('date', '>=', curdate())->where('Status', '=', 'A')->count('AppID');
return view('home', compact('data'));
It's not working at all.
So along with the answers in the comments:
public function index()
{
// First query with DB::raw() variant
$data = DB::table('toutcome')
->where('date', '>=', DB::raw('curdate()'))
->where('Status', '=', 'A')
->count('AppID');
// Second query with Carbon variant
$data2 = DB::table('toutcome')
->where('date', '>=', Carbon::now())
->where('Status', '=', 'A')
->count('AppID');
// Third query with '#Sunny' whereRaw variant
$data3 = DB::table('toutcome')
->whereRaw('date >= curdate()')
->where('Status', '=', 'A')
->count('AppID');
return view('home', compact('data','data2','data3'));
}
I'm not a big fan of compact() personally so I would write:
return view('home', ['data'=>&$data,'data2'=>&$data2,'data3'=>&$data3])
although personally (if you want to read on taking it further) read up on ViewComposers:
https://laravel.com/docs/master/views#view-composers
Change
where('date', '>=', curdate())
to
whereRaw('date >= curdate()')