Laravel Query Builder - IN operator - laravel

I'm trying to build a query joining multiple tables and I'm having trouble writing a join using an IN operator. Here's an example:
LEFT JOIN sProductDetailWarehouse pdw ON (pdw.ID_sProductDetail = pd.ID AND pdw.ID_sWarehouse IN (52,118))
The two values are set and don't need to be parameters....but this doesn't work since there is no IN operator:
->leftJoin('sProductDetailWarehouse as pdw', function($join)
{
$join->on('pdw.ID_sProductDetail', '=', 'pd.ID');
$join->on('pdw.ID_sWarehouse','IN',DB::raw("(52,118)"));
})
How can I do that join? I'm sure there's a way to do it, I just can't find it...

When you need to join to data you need to use a 'where' method instead of 'on'
e.g.
->leftJoin('sProductDetailWarehouse as pdw', function($join)
{
$join->on('pdw.ID_sProductDetail', '=', 'pd.ID');
$join->whereIn('pdw.ID_sWarehouse',[52,118]);
})

Related

Laravel 8 - How I do where clause in table added with join

Hi I want to know how can i do this query in Laravel 8 , I tried adding the join clause but not work as expected, i need join clause? Or maybe there is another form to do it. I search others examples but i donĀ“t see anythat help me. The query is the next:
DB::table('escandallo_p as esc')
->select("esc.material", "esc.referencia", "esc.ancho", "esc.proveedor", "esc.punto",
"esc.precio", "esc.consumo", "esc.veces", "esc.001", "esc.002", "esc.003", "esc.004",
"esc.005", "esc.006", "esc.007", "esc.008", "esc.009", "esc.010", "esc.011", "esc.um", "esc.merma", "esc.importe", "esc.tipo", "esc.xtalla", "esc.fase",
DB::raw("(select anulado from prototipos_p as p where p.prototipo = '".$scandal[0]->prototipo."' and p.tipo = 'c' and p.referencia = esc.referencia )"),
// ignore
//original query "(select anulado from prototipos_p as p where p.prototipo = ",$request->prototipo," and p.tipo = 'c' and p.referencia = esc.referencia ) as 'anulado'",
// "(select clase from prototipos_p as p where p.prototipo = ",$request->prototipo," and p.tipo = 'c' and p.referencia = esc.referencia ) as 'clase'")
//Converted query ->select('pro.anulado')->where('pro.prototipo', $request->prototipo)
// ->where("p.prototipo", "=", $request->prototipo)
->where("esc.id_escandallo", "=", $request->id_escandallo)
->where("esc.id_version", "=", $request->version)
->orderBy("id","asc")
->get();
!!!! I need to pass the esc.referencia to the sub select query
The second select is the conversion of the select inside "" ( i know this is wrong is only for explain it).
Thank you in advance for any suggestion.
Best regards
EDIT: I can solve my problem with DB::raw, but if anyone know others methos are welcome!
You need to pass callback to the join query to add the extra query to the laravel's join method,
Example from Laravel Doc:
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
It is explained in Laravel's doc, Advanced Join Clauses
There is Subquery support too Subquery Joins,
Eg:
$latestPosts = DB::table('posts')
->select('user_id', DB::raw('MAX(created_at) as last_post_created_at'))
->where('is_published', true)
->groupBy('user_id');
$users = DB::table('users')
->joinSub($latestPosts, 'latest_posts', function ($join) {
$join->on('users.id', '=', 'latest_posts.user_id');
})
->get();
These two might help you to achieve what you are trying
After test joins, joinSub, whereIn and other forms of doing this, I solved my problem using the DB::raw():
DB::table('escandallo_p as esc')
->select('parameters',....,
DB::raw("(SELECT column //(ONLY ONE)
FROM table
WHERE column = '".$parameter."' ...) AS nombre"),
)
->where('column', "=", $parameter)
->orderBy("id","asc")
->get();

How to write Joins inside Left join in Laravel

I have a query which has sub query with 2 joins inside a Left join and I was trying to convert it to Laravel
LEFT JOIN (
orders xo
JOIN factories xs
ON ( xs.factory_id = xo.factory_id )
JOIN setup sp
ON ( sp.factory_id = xs.legacy_factory_id)
)
ON ( xo.production_id = po.production_id )
I tried something like this
->leftJoin('orders AS xo', function ($query) use ($input) {
$query->join('factories AS xs','xs.factory_id','=','xo.factory_id')
->join('setup AS sp','sp.factory_id','=','xs.legacy_factory_id');
},function($join) {
$join->on('xo.production_id','=','po.production_id');
Would like some help with this convertion
You can use Subquery Joins like so
$SubQuery= DB::table('orders AS xo')
->join('factories AS xs','xs.factory_id','=','xo.factory_id')
->join('setup AS sp','sp.factory_id','=','xs.legacy_factory_id');
// then use the subQuery like below:
// here a is the alias to the subquery
DB::table('your_table as po')
->leftjoinSub($SubQuery, 'a', function ($join) { $join->on('a.production_id', '=', 'po.production_id'); })
There was a problem that you don't wanna do Eloquent: Relationships?
look the below link:
https://laravel.com/docs/9.x/eloquent-relationships#main-content
Additionally, You will need a patch for this problem hasOne or hasMany.

Adding a nested join 'in' Laravel Eloquent

I want to join a table based on a couple of constraints, one of which is "where a value is IN an array".
I have this code as part of a complext query builder:
$query->leftJoin('product_variable_values as val_alias, function ($join) use($rule) {
$join->on('products.id', '=', 'val_alias.product_id')
->on('val_alias.product_variable_option_id', 'in', '(1,2,3)');
});
Which outputs something like this:
left join `product_variable_values` as `val_ingredients` on `products`.`id` = `val_ingredients`.`product_id` and `val_ingredients`.`product_variable_option_id` = IN where `products`.`product_id`
You will notice that there is an error in the mysql statement because I use IN as the operator which is not allowed.
Offending code:
->on('val_alias.product_variable_option_id', 'in', '(1,2,3)');:
Offending output:
val_ingredients`.`product_variable_option_id` = IN where `products`.`product_id
What is the correct way to do this?
it same as :
$array = array(1,2,3);
$query->leftJoin('product_variable_values', 'products.id', '=', 'product_variable_values.product_id')
->whereIn('product_variable_values.product_variable_option_id', $array)

What is wrong with laravel query builder query?

I have written a query to fetch the data from mysql database using laravel query builder. Take a look at query builder code given below:
$products = DB::table("products as p")
->select("p.*")
->join("product_tag as pt", "pt.p_id", "p.id")
->whereIn("pt.tag_name", function($q1) use($request){
$q1->from("user_questionnaire as uc")
->select(DB::raw("distinct(at.prod_tag)"))
->join("questionnaire_answers as qa", function($join){
$join->on("qa.question_id", "=", "uc.question_id")
->where("qa.answer_number", "=", "uc.answer_id");
})
->join("answer_tags as at", "at.answer_id", "qa.id")
->where("uc.user_id", $request->user_id);
})->get();
When i log this query builder, i get below response:
[
{
"query": "select `p`.* from `products` as `p` inner join `product_tag` as `pt` on `pt`.`p_id` = `p`.`id` where `pt`.`tag_name` in (select distinct(at.prod_tag) from `user_questionnaire` as `uc` inner join `questionnaire_answers` as `qa` on `qa`.`question_id` = `uc`.`question_id` and `qa`.`answer_number` = ? inner join `answer_tags` as `at` on `at`.`answer_id` = `qa`.`id` where `uc`.`user_id` = ?)",
"bindings": [
"uc.answer_id",
115
],
"time": 0.43
}
]
Now when i run this query in phpmyadmin, it returns desired results. But when print_r $products variable, it displays empty array([]).
Please suggest what i am doing wrong in query builder.
Your problem is that you're using a ->where() to apply extra criteria to your innermost join:
->where("qa.answer_number", "=", "uc.answer_id");
In this case, the 3rd parameter is being bound into the query as a string so your database will be comparing the qa.answer_number field to the string uc.answer_id which is probably not what you're looking for. When you do a where, the 3rd (or the 2nd if you omit the operator) will always be added to the query bindings which is what results in this behaviour.
To get around this, you should use another ->on(...) to add additional criteria to the join:
$join->on("qa.question_id", "=", "uc.question_id")
->on("qa.answer_number", "=", "uc.answer_id");
That will make sure that the database is comparing columns to columns rather than columns to values.

Laravel 5.6 Custom Query Build showing empty result

No errors, just an empty result. I am trying to work out why this query within a model is showing an empty collection.
Mysql Workbench query:
select
u.`name`, u.email, ual.admin, a.account_name
from
users as u
join users_account_link as ual on u.id = ual.user_id and u.account_id_in_use = ual.account_id
join accounts a on ual.account_id = a.id
where
u.sub = 'ABCDE';
Spits one row containing the desired result set.
Recreating this in Laravel query builder:
$settings = DB::table('users as u')
->join('users_account_link as ual', function ($join) {
$join->on('u.id', '=', 'ual.user_id')
->where('u.account_id_in_use', '=', 'ual.account_id');
})
->join('accounts as a', 'ual.account_id', '=', 'a.id')
->select('u.name as user_name', 'u.email as user_email', 'ual.admin as admin_check', 'a.account_name')
->where('u.sub',auth()->user()->sub)
->get();
dd($settings);
Provides an empty collection. I have done many custom queries which work well however the problem I have narrowed down the result set is the additional condition for join users_account_link as ual on u.id = ual.user_id and u.account_id_in_use = ual.account_id and have tried to move this condition to a where clause which still provides an empty result.
'u.account_id_in_use', '=', 'ual.account_id' are both integers however replacing u.account_id_in_use with a hardcoded integer e.g. 2 would return a result. Therefore, Laravel seems to have an issue with this field and replaced the where-> with a whereRaw now returns the desired result.
For anyone having a similar issue, try replacing fields with hardcode values to isolate the issue and look into using raw when possible to overcome the issue.
Hope this helps anyone in need.

Resources