Laravel Query Builder Stop working after groupBy - laravel

$records = DB::table('history as a')
->join('reservation2 as b', function($join){
$join->on('a.id', '=', 'b.id')
->on('a.sid', '=', 'b.sid');
})
->whereBetween('a.date', [$sDate, $eDate])
->select('a.*', DB::raw('SUM(a.perday) AS revenue'), 'b.name', 'b.checkin', 'b.checkout', 'b.status')
->groupBy('a.id')
->groupBy('a.sid')
->toSql();
Gives me following query:
select `a`.*, SUM(a.perday) AS revenue, `b`.`name`, `b`.`checkin`, `b`.`checkout`,
`b`.`status`
from `history` as `a`
inner join `reservation2` as `b` on `a`.`id` = `b`.`id` and `a`.`sid` = `b`.`sid`
where `a`.`date` between ? and ? group by `a`.`id`, `a`.`sid`
Many records are displayed if query is passed from mysql command prompt but if I replace ->toSql() with ->get() it does not give me any record.
What is the problem?

Related

Eloquent - Join a Subquery

I have a complicated query that I would like to translate either in Eloquent ORM or with the Query Builder for a Laravel site, but I can't do it, can someone help me?
Here is my SQL query
SELECT opp_id, risk_study.rst_id, risk_study.rst_status
FROM opportunity
LEFT JOIN risk_study ON risk_study.rst_id =
(SELECT risk_study_quote_vehicle.rst_id
FROM risk_study_quote_vehicle
INNER JOIN quote_vehicle ON quote_vehicle.quv_id = risk_study_quote_vehicle.quv_id
INNER JOIN quote ON quote.quo_id = quote_vehicle.quo_id
WHERE quote.opp_id = opportunity.opp_id
ORDER BY risk_study_quote_vehicle.rst_id DESC
LIMIT 0,1)
WHERE 1 = 1
AND opportunity.per_id_process = '5'
AND opportunity.opp_locked = '1'
Here is my solution.
But this query does not retrieve values from the risk_study table.
$opportunities = Opportunity::select('opp_id', 'risk_study.rst_id', 'risk_study.rst_status')
->leftJoin('risk_study', function ($join) {
$join->on('risk_study.rst_id', '=', DB::raw('"SELECT risk_study_quote_vehicle.rst_id FROM risk_study_quote_vehicle INNER JOIN quote_vehicle ON quote_vehicle.quv_id = risk_study_quote_vehicle.quv_id INNER JOIN quote ON quote.quo_id = quote_vehicle.quo_id WHERE quote.opp_id = opportunity.opp_id ORDER BY risk_study_quote_vehicle.rst_id DESC LIMIT 0,1"'));
})
->where([
['per_id_process', 5],
['opp_locked', 1],
])
->get();
Finally, I wrote the query and it works ! Thanks !
$opportunities = Opportunity::query()
->select(
'opp_id',
'risk_study.rst_id',
'risk_study.rst_status'
)
->from('opportunity')
->leftJoin('risk_study', function ($join) {
$join->where('risk_study.rst_id', function ($sub) {
$sub->select('risk_study_quote_vehicle.rst_id')
->from('risk_study_quote_vehicle')
->join('quote_vehicle', 'quote_vehicle.quv_id', 'risk_study_quote_vehicle.quv_id')
->join('quote', 'quote.quo_id', 'quote_vehicle.quo_id')
->whereColumn('quote.opp_id', 'opportunity.opp_id')
->orderByDesc('risk_study_quote_vehicle.rst_id')
->limit(1);
});
})
->where('opportunity.per_id_process', '5')
->where('opportunity.opp_locked', '1')
->get();
You should be able to use a Closure as the second parameter of where() inside your join Closure.
I don't think Laravel's query builder supports the LIMIT 0,1 statement.
I don't know why you need WHERE 1 = 1, but you should be able to use whereRaw for that.
When you're done, the result looks very alike a formatted SQL query.
$opportunities = Opportunity::query()
->select(
'opp_id',
'risk_study.rst_id',
'risk_study.rst_status'
)
->from('opportunity')
->leftJoin('risk_study', function ($join) {
$join->where('risk_study_quote_vehicle.rst_id', function ($sub) {
$sub->select('risk_study_quote_vehicle.rst_id')
->from('risk_study_quote_vehicle')
->join('quote_vehicle', 'quote_vehicle.quv.id', 'risk_study_quote_vehicle.quv_id')
->join('quote', 'quote.quo_id', 'quote_vehicle.quo_id')
->where('quote_opp_id', 'opportunity.opp_id')
->orderByDesc('risk_study_quote_vehicle.rst_id')
->limit(1);
});
})
->whereRaw('1 = 1')
->where('opportunity.per_id_process', '5')
->where('opportunity.opp_locked', '1')
->get();

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 do this sentence in query builder

I have a question, i need do this query in query builder:
SELECT
ps_orders.id_order,
ps_customer.firstname,
ps_customer.lastname,
ps_customer.email,
ps_address.address1,
ps_address.postcode,
ps_address.city,
ps_address.phone_mobile,
ps_orders.id_order,
ps_orders.reference,
ps_order_detail.product_name,
ps_order_detail.product_quantity,
ps_shop.name AS tienda,
ps_carrier.name AS transportista
FROM
ps_customer
INNER JOIN ps_address ON ps_customer.id_customer = ps_address.id_customer
INNER JOIN ps_orders ON ps_address.id_customer =
ps_orders.id_customer AND ps_orders.id_address_delivery =
ps_address.id_address
INNER JOIN ps_order_detail ON ps_orders.id_order =
ps_order_detail.id_order
INNER JOIN ps_shop ON ps_order_detail.id_shop = ps_shop.id_shop
INNER JOIN ps_carrier ON ps_orders.id_carrier = ps_carrier.id_carrier
WHERE
ps_orders.id_order =54
I did this query in query builder:
$naviones=DB::connection('naviones')->table('ps_customer')
->join('ps_address','ps_customer.id_customer','=','ps_address.id_customer')
->join('ps_orders','ps_address.id_customer','=','ps_orders.id_customer')
->join('ps_order_detail','ps_orders.id_order','=','ps_order_detail.id_order')
->join('ps_shop','ps_order_detail.id_shop','=','ps_shop.id_shop')
->join('ps_carrier','ps_orders.id_carrier','=','ps_carrier.id_carrier')
->select('ps_orders.id_address_delivery','ps_orders.id_order','ps_customer.firstname','ps_customer.lastname','ps_customer.email','ps_address.address1',
'ps_address.postcode','ps_address.city','ps_address.phone_mobile','ps_orders.id_order','ps_orders.reference',
'ps_order_detail.product_name','ps_order_detail.product_quantity','ps_shop.name as tienda','ps_carrier.name as transportista')
->where('ps_orders.id_order','=',$idpedido)->get();
My question is: How can i do for made this query section?
INNER JOIN ps_orders ON ps_address.id_customer =
ps_orders.id_customer AND ps_orders.id_address_delivery =
ps_address.id_address
I hope that yours will can help me. Thank you.
You can use join something like this
->join('table2 AS b', function($join){
$join->on('a.field1', '=', 'b.field2')
->where('b.field3', '=', true)
->where('b.field4', '=', '1');
})
in case if you don't want to compare then you can use multiple "on" chained function like below
$query->join('ps_orders', function($join)
{
$join->on('ps_orders.id', '=', 'ps_address.id_customer')
->on('ps_orders.id_address_delivery', '=', 'ps_address.id_address')
});

Convert raw SQL to use Eloquent Query Builder

How can I convert the following complex SQL query to use the Eloquent query builder? I want to use methods such as join() and where(), get() etc.
The below query returns a list of locations along with counts for vouchers that have been redeemed.
select
a.location_name,
'' as dates,
a.places,
sum(netvalue155),
sum(netvalue135) from
(
select
l.id,
l.location_name,
b.places,
case when v.net_value = 155 then 1 else 0 end as netvalue155,
case when v.net_value = 135 then 1 else 0 end as netvalue135
from locations l
left join bookings b on l.id = b.location_id
left join vouchers v on b.voucher_code = v.voucher_code
) a
right join locations l on l.id = a.id
group by a.location_name
EDIT
I am trying the below code, which throws the error SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sub.id' in on clause
$subQuery = DB::table('locations')
->select(
'locations.id',
'locations.location_name',
DB::raw('"'.$request->get('dates').'" as dates'),
DB::raw('sum(bookings.id) as number'),
DB::raw('round(sum(bookings.final_price/1.2), 2) as paidbycard'),
DB::raw('case when bookings.voucher_value = 155 then round(sum(bookings.voucher_value/1.2), 2) else 0.00 end as voucher155'),
DB::raw('case when bookings.voucher_value = 135 then round(sum(bookings.voucher_value/1.2), 2) else 0.00 end as voucher135'),
DB::raw('case when bookings.transfer_fee = 10 then round(sum(bookings.transfer_fee/1.2), 2) else 0.00 end as transfer_fee'))
->leftJoin('bookings', 'locations.id', '=', 'bookings.location_id');
$meatBookQuery = DB::table('orders')->select(DB::raw('sum(orders_items.price) as total'))
->join('orders_items', 'orders.id', '=', 'orders_items.order_id')
->where('orders_items.item_name', 'The Meat Book');
$booking = DB::table(DB::raw("({$subQuery->toSql()}) as sub, ({$meatBookQuery->toSql()}) as meatBook"))
->mergeBindings($subQuery)
->mergeBindings($meatBookQuery)
->select('sub.location_name', 'sub.dates', 'sub.number', 'sub.paidbycard', 'sub.voucher155', 'sub.voucher135', 'sub.transfer_fee', DB::raw('round(sum(sub.voucher155 + sub.voucher135 + sub.transfer_fee + sub.paidbycard), 2) as total'), 'meatBook.total')
->leftJoin('locations', 'locations.id', '=', 'sub.id')
->leftJoin('bookings', 'bookings.location_id', '=', 'sub.id')
->groupBy('sub.location_name');
First of all
I often see people asking for how to rebuild a complex SQL query in Laravels Query Builder. But not every operation which is possible in SQL or MySQL is implemented as a function in Laravels Query Builder. This means you can't rebuild every SQL query in Query Builder without using raw SQL.
What does this mean for your SQL query?
Some things like sub queries (the from (select ...) part) and the case when ... part is not implemented in Query Builder. At least therefore you will have to use the raw expression with the DB::raw() function. I'm not sure about the sum() if this is already possible but you will surely find that in the docs.
Other things like joins are implemented as a function:
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.id', 'contacts.phone', 'orders.price')
->get();
see Laravel Documentation: Queries - Joins
And you can even mix up Query Builder functions with raw expressions:
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
see Laravel Documentation: Queries - Raw Expression
Example for a sub query:
$subQuery = DB::table('locations')
->leftJoin('bookings', 'locations.id', '=', 'bookings.location_id')
->leftJoin('vouchers', 'bookings.voucher_code', '=', 'vouchers.voucher_code')
->select('locations.id', 'locations.location_name', 'bookings.places');
$query = DB::table(DB::raw("({$subQuery->toSql()} as sub"))
->mergeBindings($subQuery)
->select(...)
->rightJoin(...)
->groupBy('sub.location_name')
->get();
So you can rebuild some parts of the query in Query Builder and use raw expressions wherever you need to.
To debug a query while you build it Laravels query logging function can be very helpful.

Equivalent Eloquent Query

What's the equivalent eloquent query for:
SELECT `ip`
FROM items INNER JOIN ips ON items.client_id = ips.cient_id
WHERE serial_key = 12345
I have come up with this:
DB::table('items')
->join('ips', 'items.cient_id', '=', 'ips.client_id')
->where('items.serial_key', Request::get('serial_key'))
->select('ip')
->first();
It returns NULL.
How do I know that if it finds a record too?
You have a typo in the call to join():
join('ips', 'items.cient_id', '=', 'ips.client_id')
^^^^^^^^

Resources