I have two tables, salaries
and pointages
, and a belongsTo
/hasMany
relationship between them. I want to select the sum of the sold
and payer
columns on condition of date and condition of salarie_id
and chantier_id
. I want to be optional, if I choose salarie_id
or chantier_id
, I want to give me either the pointages
of salarie_id
or chantier_id
chosen or both. But in my case even when I chose salarie_id
or chantier_id
, it showed me all of the rows.
$dataP = DB::table('salaries')
->join('pointages','pointages.salarie_id','salaries.id')
->selectRaw('SUM(pointages.sold) as sold,salaries.nom,salaries.prenom,salaries.id,SUM(pointages.payer) as payer')
->whereRaw(DB::raw('YEAR(pointages.datep) = ' .$request->annee))
->whereRaw(DB::raw('MONTH(pointages.datep) = ' .$request->mois))
->whereRaw( DB::raw('DAY(pointages.datep)>0 AND DAY(pointages.datep)<16'))
->Orwhere('pointages.salarie_id','=',$request->salarie_id)
->OrWhere('pointages.chantier_id','=',$request->chantier_id)
->groupBy('pointages.salarie_id')
->get();
return response($dataP);
I suspect you aren't familiar with how where
/whereRaw
and orWhere
/orWhereRaw
work when combined.
Currently your WHERE
clause looks like this:
YEAR(pointages.datep) = ? and MONTH(pointages.datep) = ? and DAY(pointages.datep)>0 AND DAY(pointages.datep)<16 or `pointages`.`salarie_id` = ? or `pointages`.`chantier_id` = ?
Note no parentheses, meaning either of the final conditions can override the earlier ones. You can easily determine what your query will look like by using the toSql()
or dd()
query builder methods.
My guess is that you're looking for a query like this?
SELECT SUM(pointages.sold) AS sold, SUM(pointages.payer) AS payer,
salaries.nom, salaries.prenom, salaries.id
FROM salaries
LEFT JOIN pointages ON (pointages.salarie_id = salaries.id)
WHERE YEAR(pointages.datep) = ?
AND MONTH(pointages.datep) = ?
AND DAY(pointages.datep) > 0
AND DAY(pointages.datep) < 16
AND (
pointages.salarie_id = ?
OR pointages.chantier_id = ?
)
GROUP BY pointages.salarie_id
So a couple of notes first: 1) don't ever put raw data into an SQL query like you're doing above. The whereRaw()
method works with placeholders; use them. 2) Try to avoid using raw statements at all where possible. There are helper functions to do things like the date calculations you're doing. 3) Grouping your constraints is done by passing a closure to where()
/orWhere()
. 4) Performing comparisons against function results (like you're doing with your YEAR
, MONTH
, and DAY
functions) is very inefficient; the column effectively becomes an unindexed text column.
The following code will produce a query equivalent to the above, but makes the checks from the request optional:
$dateStart = Carbon\Carbon::create($request->annee, $request->mois, 1, 0, 0, 0);
$dateEnd = $dateStart->addDays(15)->subSecond(1);
DB::table('salaries')
->leftJoin('pointages', 'pointages.salarie_id', 'salaries.id')
->select(['salaries.nom', 'salaries.prenom', 'salaries.id'])
->selectRaw('SUM(pointages.sold) AS sold')
->selectRaw('SUM(pointages.payer) AS payer')
->whereBetween('pointages.datep', [$dateStart, $dateEnd])
->where(function($q) use($request) {
if ($request->has('salarie_id')) {
$q->orWhere('pointages.salarie_id', $request->salarie_id);
}
if ($request->has('chantier_id')) {
$q->orWhere('pointages.chantier_id', $request->chantier_id);
}
})
->groupBy('pointages.salarie_id')
->get();