如何将以下复杂SQL查询转换为使用Eloquent查询构建器?我想使用join()
和where()
,get()
等方法。
以下查询会返回一个地点列表以及已兑换凭证的计数。
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
修改
我正在尝试下面的代码,它会抛出错误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');
答案 0 :(得分:2)
我经常看到人们在Laravels Query Builder中询问如何重建复杂的SQL查询。但并非每个SQL或MySQL中可能的操作都是作为Laravels Query Builder中的函数实现的。这意味着您无需使用原始SQL即可在Query Builder中重建每个 SQL查询。
在查询生成器中未实现子查询(from (select ...)
部分)和case when ...
部分等内容。因此,至少您必须使用带有DB::raw()
函数的原始表达式。我不确定sum()
是否已经可以,但你肯定会在文档中找到它。
joins
等其他内容作为函数实现:
$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();
请参阅Laravel文档:Queries - Joins
您甚至可以将查询生成器函数与原始表达式混合使用:
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
请参阅Laravel文档:Queries - Raw Expression
子查询的示例:
$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();
因此,您可以在查询生成器中重建查询的某些部分,并在需要的地方使用原始表达式。
要在构建查询时调试查询,Laravels query logging函数可能非常有用。