Use `AND` in Laravel Query Builder, syntax error (orOn) - mysql

I have this sql (MariaDB) query, it works ok:
SELECT
admin_combustibles.nombre,
admin_combustibles.id_combustible,
admin_combustible_unidades.nombre AS unidades,
admin_tipo_combustibles.nombre AS tipo_combustible,
admin_indice_combustibles.valor_combustible
FROM
admin_combustibles
INNER JOIN admin_combustible_unidades ON admin_combustibles.combustible_unidades_id = admin_combustible_unidades.id_combustible_unidad
INNER JOIN admin_tipo_combustibles ON admin_combustibles.tipo_combustible_id = admin_tipo_combustibles.id_tipo_combustible
LEFT JOIN admin_indice_combustibles ON admin_combustibles.id_combustible = admin_indice_combustibles.combustible_id
AND admin_indice_combustibles.anio = 1992
AND admin_indice_combustibles.mes = 6
ORDER BY
admin_combustibles.nombre
But when I try to make it through Laravel, I have some error because Laravel put some on the number 1992, in that way the query doesn't work.
Plus, I don't know how to do the AND on Laravel, I only have orOn but it doesn't work:
$datos = AdminCombustible::select([
'admin_combustibles.nombre',
'admin_combustibles.id_combustible',
'admin_combustible_unidades.nombre AS unidades',
'admin_tipo_combustibles.nombre AS tipo_combustible',
'admin_indice_combustibles.valor_combustible'])
->join('admin_combustible_unidades', 'admin_combustibles.combustible_unidades_id', '=', 'admin_combustible_unidades.id_combustible_unidad')
->join('admin_tipo_combustibles', 'admin_combustibles.tipo_combustible_id', '=', 'admin_tipo_combustibles.id_tipo_combustible')
->leftJoin('admin_indice_combustibles', function ($join) {
$join->on('admin_indice_combustibles.combustible_id', '=', 'admin_combustibles.id_combustible')->orOn('admin_indice_combustibles.anio', '=', 1992);
})
->get();
dd($datos);
I got an sql syntax error.
Any help on how to make that query with query builder of Laravel? (I put the entire query as DB::raw and it works, but I don't want to use raw() )

I think there might be two problems here. Since you are using and in your original query, you might be needing to use or instead of orOn on your join.
Also you will need to use DB::raw() on the parameters, otherwise Laravel will consider them columns....
$join->on('admin_indice_combustibles.combustible_id', '=', 'admin_combustibles.id_combustible')->on('admin_indice_combustibles.anio', '=', DB::raw('1992'));

Related

Rewrite MYSQL query using Laravel query builder

I'm trying to rewrite MYSQL query using Laravel query builder
So this is the query
DB::select("SELECT * FROM accomodation WHERE id NOT IN
(SELECT accomodation_id FROM bookings
WHERE (`checkin` <= '$request->in' AND `checkout` >= '$request->out'));");
And this is what I've done so far
Accommodation::whereNotIN('id', function($q)
{
$q->select('accomodation_id')
->from('bookings')
->where('checkin', '<=', '$request->out')
->where ('checkout', '>=', '$request->in');
})
->get();
The problem is the first query is giving me expected results but the second one isn't
Can someone point out what I'm doing wrong?
I think you type it wrong. Look at the $request->in and $request->out. You may want to flip it. and why you use '$request->in' instead of $request->in. It will parse as string instead of the value
You don't have use. For example php Accommodation::whereNotIN('id', function($q) use ($request) and you need to flip condition with request ;)

How to refactor Laravel Eloquent Query

I have a query that retrieves data from 5 tables using joins. While I obtain the right result, it's quite slow.
The tables:
data_bundles
vendors
ussd_strings
products users
data_bundles_category
How can I refactor this?
Also, the setup does not use models.
$data_bundle_transaction = DB::table('data_bundles')
->select('*','data_bundles.phone_number as data_bundles_phone_number')
->join('vendors','vendors.vendor_id','=','data_bundles.vendor_id')
->join('ussd_strings','data_bundles.product_id','=','ussd_strings.product_id')
->join('products','data_bundles.product_id','=','products.product_id')
->join('users','users.user_id','=','data_bundles.user_id')
->leftJoin('data_bundle_category', 'data_bundle_category.product_id', '=', 'data_bundles.product_id')
->where('data_bundles.status',0)
->where('data_bundles.network','like', '%' . $request->network.'%')
->where('data_bundle_category.data_category', '=', $request->type)->first();
You could try using joins with multiple conditions, this way you will join less data and query will be faster
$data_bundle_transaction = DB::table('data_bundles')
->select('*','data_bundles.phone_number as data_bundles_phone_number')
->join('vendors','vendors.vendor_id','=','data_bundles.vendor_id')
->join('ussd_strings','data_bundles.product_id','=','ussd_strings.product_id')
->join('products','data_bundles.product_id','=','products.product_id')
->join('users','users.user_id','=','data_bundles.user_id')
->leftJoin('data_bundle_category', function() use ($request){
$join->on('data_bundle_category.product_id', '=', 'data_bundles.product_id');
$join->on('data_bundle_category.data_category', '=', $request->type);
})
->where('data_bundles.status',0)
->where('data_bundles.network','like', '%' . $request->network.'%')
->first();

Want to get result between time range in Laravel

I have some records, i want to get records from them where item is not between given time range, here is my code that i already tried but no success
$other_hour_trade = DB::table('finaltrade')
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->select('finaltrade.*')
->where('finaltrade.user_id', $user_id)
->whereNotBetween('finaltrade.created_at', [DB::raw('exchanges.start_time'), DB::raw("ADDTIME(exchanges.start_time, '01:00:00')")])
->whereNotBetween('finaltrade.created_at', [DB::raw('exchanges.close_time'), DB::raw("SUBTIME(exchanges.close_time, '01:00:00')")])
->get();
'finaltrade.created_at' is a datetime field and
'exchanges.start_time' and 'exchanges.close_time' is a only time field
I have join two tables to get results
I don't know how to make this work directly using whereNotBetween, but since you're already trying to resort to some raw SQL in your current code, why not just use whereRaw instead:
$other_hour_trade = DB::table('finaltrade')
->join('exchanges', 'finaltrade.exchange_id', '=', 'exchanges.id')
->select('finaltrade.*')
->where('finaltrade.user_id', $user_id)
->whereRaw("finaltrade.created_at NOT BETWEEN exchanges.start_time AND ADDTIME(exchanges.start_time, '01:00:00')")
->whereRaw("finaltrade.created_at NOT BETWEEN exchanges.close_time AND SUBTIME(exchanges.close_time, '01:00:00')")
->get();

Raw Mysql query working on phpMyAdmin returning error in laravel

I have this Eloquent query:
return DB::table('users')
->leftJoin('bet', function($join) use ($competition_id){
$join->on('users.id', '=', 'bet.user_id');
$join->on('bet.competition_id','=', DB::raw("$competition_id"));
})
->select('users.*', DB::raw('SUM(points) as score'))->get();
it returns me an error:
SQLSTATE[42000]: Syntax error or access violation: 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause (SQL: select users.*, SUM(points) as score from users left join bet on users.id = bet.user_id and bet.competition_id = 1)
if I just copy-paste the generated SQL (in bold) in PhpMyAdmin, it works perfectly...
Could you please help me solving this issue? because it makes no sense to me...
Thank you
SOLUTION
The problem was just the missing group by:
return DB::table('users')
->leftJoin('bet', function($join) use ($competition_id){
$join->on('users.id', '=', 'bet.user_id');
$join->on('bet.competition_id','=', DB::raw("$competition_id"));
})
->select('users.*', DB::raw('SUM(points) as score'))->groupBy('users.id')->get();
SOLUTION #2
Depending on the version or configuration of MySQL, the solution above is not working and I had to groupBy all the fields as advised by Eric:
return DB::table('users')
->leftJoin('bet', function ($join) use ($competition_id) {
$join->on('users.id', '=', 'bet.user_id');
$join->on('bet.competition_id', '=', DB::raw("$competition_id"));
})
->select('users.*', DB::raw('SUM(points) as score'))
->groupBy('users.id')
->groupBy('users.name')
->groupBy('users.firstName')
->groupBy('users.lastName')
->groupBy('users.email')
->groupBy('users.admin')
->groupBy('users.password')
->groupBy('users.remember_token')
->groupBy('users.created_at')
->groupBy('users.updated_at')->get();
}
I have many questions but 4. is the cause of it
Why aren't you using the ORM? You should take advantage of the framework whenever possible
Why DB::raw on $competition_id? it's just a value you're inserting into the query
You can use selectRaw on your final select to avoid another DB::raw
It is most likely the lack of a groupBy (your sum is at fault). You can do this by placing a group by or disabling strict mode on MySql
Try this:
return DB::table('users')
->leftJoin('bet', function($join) use ($competition_id){
$join->on('users.id', '=', 'bet.user_id');
$join->on('bet.competition_id','=', DB::raw("$competition_id"));
})
->select('users.*', DB::raw('SUM(points) as score'))->groupBy('users.id')->get();

Translate Laravel function to SQL request to test

I would like to test the output of Laravel function in MySQL, for this I need to translate the code to SQL request.
Function :
return DB::table('products')
->leftJoin('product_locations', 'products.id', '=', 'product_locations.productId')
->select(DB::raw('IF(product_locations.id is not null,concat(product_locations.id,"-","M"),concat(products.id,"-","N")) as id'), DB::raw('IF(product_locations.id is not null,1,0) as multilocation'), 'products.productName', 'products.productName as text', 'product_locations.productLocationName', 'product_locations.binLocationName', 'product_locations.unitCost', 'product_locations.amount')
->orderBy('products.productName')
->distinct()
->get();
Use query logging:
DB::connection()->enableQueryLog();
DB::table('products')
->leftJoin('product_locations', 'products.id', '=', 'product_locations.productId')
->select(DB::raw('IF(product_locations.id is not null,concat(product_locations.id,"-","M"),concat(products.id,"-","N")) as id'), DB::raw('IF(product_locations.id is not null,1,0) as multilocation'), 'products.productName', 'products.productName as text', 'product_locations.productLocationName', 'product_locations.binLocationName', 'product_locations.unitCost', 'product_locations.amount')
->orderBy('products.productName')
->distinct()
->get();
dd(DB::getQueryLog())
It is not the way, but still you can get the same result with less effort.
Make a small mistake in you query, for example use remove last character of a table name or a column name. Then it raise an error that shows the query. Then you can easily get your query on the screen.
In your query, use product instead of products. This will cause an error in query and display it.