subquery inside orWhere in laravel - laravel

I need assistance to build up the query like below in laravel:
SELECT *
FROM table t
WHERE t.a = 1
OR (t.a=0
AND t.id IN (
SELECT o.a_id
FROM other_table o
WHERE o.x > 3
)
);

You could try to build your exact current query, and in fact it might even be the most efficient to write it. But, if we rephrase your query using a left join, it becomes somewhat easier to express in Laravel code.
SELECT *
FROM your_table t
LEFT JOIN other_table o
ON t.id = o.a_id AND o.x > 3
WHERE
t.a = 1 OR
(t.a = 0 AND o.a_id IS NOT NULL);
This would translate to the following Laravel code:
$result = DB::table('your_table t')
->leftJoin('other_table o', function($join) {
$join->on('t.id', '=', 'o.a_id');
$join->on('o.x', '>', '3');
})
->where('t.a', '=', '1')
->orWhere(function($query) {
return $query->where('t.a', '=', '0')
->whereNotNull('o.a_id')
})
->get();

Related

Nested Select in Eloquent

I want to recreate below SQL in Eloquent (Laravel 6 LTS)
I want to avoid DB::raw as I have logics behind the PartnerPrice::class (model)
SELECT *
FROM (SELECT *,
ROW_NUMBER ()
OVER (PARTITION BY group, TYPE
ORDER BY effective_at DESC, created_at DESC)
r
FROM partner_prices
WHERE group = 'premier'
and partner_id = 8
AND TYPE = 'premium'
AND effective_at <= '2020-10-31') a
WHERE r = 1
ORDER BY group;
Here's my working inner query.
I just need help wrapping this with another select and add a where('r', 1)
$sub = PartnerPrice::select('*')
->selectRaw('ROW_NUMBER () OVER (PARTITION BY mccmnc, TYPE ORDER BY effective_at DESC, created_at DESC) r')
->where('type', $type)
->where('partner_id', $partnerId)
->where('group', $group)
->where('effective_at', '<=', now()->subMonth()->lastOfMonth())
->get();
You could use the toSql method with mergeBindings like this
$queryBuilder = PartnerPrice::select('*')
->selectRaw('ROW_NUMBER () OVER (PARTITION BY mccmnc, TYPE ORDER BY effective_at DESC, created_at DESC) r')
->where('type', $type)
->where('partner_id', $partnerId)
->where('group', $group)
->where('effective_at', '<=', now()->subMonth()->lastOfMonth());
$result = DB::table(DB::raw('(' . $queryBuilder->toSql() . ') as a'))
->mergeBindings($queryBuilder->getQuery())
->where('a.r', 1)
->get();
Note that I omitted the get() on the first builder
Also I think you can use
DB::select('*')
->fromSub($queryBuilder, 'a')
->where('a.r', 1)
->get();
But never used it. try this too.

Different result for Laravel's Eloquent And Raw Query

Anyone experienced raw SQL queries having different results with eloquent?
Here is my eloquent returning a value:
BookingRoleSchedule::from('booking_role_schedules as a')
->whereExists(function ($q) {
return $q
->select(DB::raw(1))
->from('booking_role_schedules as b')
->where('a.id', '<>', 'b.id')
->whereRaw('not(a.start_date >= b.end_date or a.end_date <= b.start_date)');
})
->join('booking_role_schedule_talent as c', function($join) {
$join->on('a.id', '=', 'c.booking_role_schedule_id')
->whereExists(function($q) {
return $q
->from('booking_role_schedule_talent as d')
->select(DB::raw(1))
->where('c.booking_role_schedule_id', '<>', 'd.booking_role_schedule_id')
->whereRaw('not(c.user_id != d.user_id)');
});
})->get();
While my SQL query doesn't return any value
select *
from `booking_role_schedules` as `a`
inner join `booking_role_schedule_talent` as `c` on `a`.`id` = `c`.`booking_role_schedule_id`
and exists(select 1
from `booking_role_schedule_talent` as `d`
where `c`.`booking_role_schedule_id` <> `d`.`booking_role_schedule_id`
and not (c.user_id != d.user_id))
where exists(select 1
from `booking_role_schedules` as `b`
where `a`.`id` <> `b`.`id`
and not (a.start_date >= b.end_date or a.end_date <= b.start_date))

SELECT COUNT in WHERE CLAUSE in Eloquent

I know that something similar was here some time ago,but it wasn't the same case and I can't just figure it out on myself.
I need to transform raw SQL query to Eloquent.
This query contains SELECT COUNT in WHERE clause, for simplicity I have this (may has not much sense) query :
SELECT u.column1, u.column2, u.column3, s.column1 FROM users u
LEFT JOIN salary s ON u.id = s.user_id
WHERE
(
SELECT count(cars_id) FROM cars WHERE cars.user_id = u.id
) = 0
AND u.city IN ("London","Paris")
I tried:
$columns = [
'users.column1',
'users.column2',
'users.column3',
'salary.column1'
];
$q = User::select($columns)
->leftJoin('salary', 'salary.user_id', '=', 'users.id')
->whereRaw(" (SELECT COUNT(cars_id) FROM cars WHERE cars.user_id = u.id) = 0 ")
->whereRaw("u.city IN ('London','Paris')")
->get();
But it doesn't return same results as raw SQL (SQL had 161 rows and Eloquent 154 rows).
Maybe you know how to transform this kind of query correctly to Eloquent?
Thanks
Based on your query I believe this should do it:
DB::table('users as u')
->select([ 'u.column1', 'u.column2', 'u.column3', 's.column1'])
->leftJoin('salary as s', 'u.id', '=', 's.user_id')
->leftJoin('cars as c', 'c.user_id', '=', 'u.id')
->whereIn('u.city', ['London', 'Paris'])
->havingRaw('count(c.id) = 0')
->get();
Please let me know.

how to create select join multiple condition in laravel 5.3

how to create select join multiple condition in laravel 5.3
SQL SELECT Statement.
SELECT table_1.column_1
,table_2.column_1
,table_3.column_1
FROM table_1
LEFT JOIN table_2
ON table_1.column_1 = table_2.column_1
LEFT JOIN table_3
ON table_1.column_2 = table_3.column_2
AND table_3.column_3 <= NOW()
AND ( table_3.column_4 >= NOW()
OR table_3.column_4 = 0
)
WHERE table_1.column_1 = '0000000001'
I want to convert SQL Statement to laravel select.
I try.
$result = DB::table('table_1')
->select('table_1.column_1', 'table_2.column_1', 'table_3.column_1')
->leftJoin('table_1', 'table_1.column_1', '=', 'table_2.column_1')
->leftJoin('table_3', 'table_1.column_2', '=', 'table_3.column_2')
->where('table_1', $_POST['id'])
->get();
DB::table('table_1')
->select('table_1.column_1', 'table_2.column_1', 'table_3.column_1')
->leftJoin('table_1', 'table_1.column_1', '=', 'table_2.column_1')
->leftJoin('table_3', 'table_1.column_2', '=', 'table_3.column_2')
->where('table_1.column_1', $_POST['id'])
->where('table_3.column_3','>=', NOW())
->where(function($query) {
$query->where('table_3.column_4', '>=', NOW())
->orWhere('table_3.column_4','0');
})
->get();

Lumen eloquent left join

I want to make some migration from Laravel to Lumen, before that every code on my Laravel working and has no error and running well. Then i found this line and eloquent in Lumen translate this different than Laravel.
DB::table('products_categories')
->select('products.*', 'brands.name as brand_name', 'categories.link_rewrite as category_link_rewrite',
'product_medias.id as id_image', 'product_stocks.quantity as product_stock', 'product_medias.path','product_medias.filename', 'specific_prices.reduction_type', 'specific_prices.reduction as reduction',
'specific_prices.reduction', 'products_categories.position')
->leftJoin('products', 'products.id', '=', 'products_categories.product_id')
->leftJoin('product_stocks', 'products.id', '=', 'product_stocks.product_id')
->leftJoin('brands', 'brands.id', '=', 'products.brand_id')
->leftjoin('product_medias', function($join){
$join->on('product_medias.product_id', '=', 'products.id')
->whereIn('product_medias.cover', [1, 0]);
})
->leftJoin('categories', 'products_categories.category_id', '=', 'categories.id')
->leftJoin('specific_prices', function($join){
$join->on('specific_prices.product_id', '=', 'products.id')
->on(DB::raw("(`specific_prices`.`from` = '0000-00-00 00:00:00' OR '".date('Y-m-d H:i:s')."' >= `specific_prices`.`from`)"), DB::raw(''), DB::raw(''));
})
->where('categories.name','=', "Special Price" )
->where('products.active','=', 1)
->whereNull('products.deleted_at')
->groupBy('products_categories.product_id')
->orderBy('products_categories.id', 'desc');
Once again it's working on my Laravel but i get 'Error' on Lumen, is there any solution to solve this?
If i dump this line the query will look like this :
select `products`.*, `brands`.`name` as `brand_name`, `categories`.`link_rewrite` as `category_link_rewrite`, `product_medias`.`id` as `id_image`, `product_stocks`.`quantity` as `product_stock`, `product_medias`.`path`, `product_medias`.`filename`, `specific_prices`.`reduction_type`, `specific_prices`.`reduction` as `reduction`, `specific_prices`.`reduction`, `products_categories`.`position` from `products_categories` left join `products` on `products`.`id` = `products_categories`.`product_id` left join `product_stocks` on `products`.`id` = `product_stocks`.`product_id` left join `brands` on `brands`.`id` = `products`.`brand_id` left join `product_medias` on `product_medias`.`product_id` = `products`.`id` and `product_medias`.`cover` in (1, 0) left join `categories` on `products_categories`.`category_id` = `categories`.`id` left join `specific_prices` on `specific_prices`.`product_id` = `products`.`id` and (`specific_prices`.`from` = '0000-00-00 00:00:00' OR '2016-11-14 09:12:44' >= `specific_prices`.`from`) = where `categories`.`name` = Special Price and `products`.`active` = 1 and `products`.`deleted_at` is null group by `products_categories`.`product_id` order by `products_categories`.`id` desc limit 10
There is equal symbol after left join specific_prices and also didn't track 'Special Price' as character

Resources