Laravel 6.0 中更加強勁的子查詢


Laravel 6.0 中更加強勁的子查詢
 

如果你一直關注我的工作,你就會知道我推崇將我們的 Laravel 應用里面的工作更多地放到數據庫層。 通過在數據庫層完成更多工作,我們通常可以減少我們制造的數據庫查詢的數量,減少應用程序使用的內存量,並減少 Eloquent 處理模型所需的時間。 這可以帶來一些非常顯着的性能提升。

將更多工作推到數據庫層的一種很好的方法是使用子查詢。 子查詢允許您在另一個數據庫查詢中運行嵌套查詢。 當無法通過關系查詢查到結果時,這是獲取輔助模型數據的強大方法,而無需進行任何額外的數據庫查詢。 您還可以在 order by 語句, where 語句和其他數據庫子句中使用子查詢。

在 Laracon US 2019 talk 期間,我參考了我正在使用的查詢構造器,這讓我們在 laravel 中使用子查詢變得更加簡單。我已經向 laravel 提交了三個 pr , 將這些添加到 laravel 的內核中.

概述:

 

“Select” 子查詢

Pull request #29567 select() 和 addSelect() 查詢構建器方法支持子查詢

舉個例子,假設我們有一個目的地表 destinations 和一個到目的地的航班表 flightsflights 表包含一個 arrival_at 字段,表示航班何時到達目的地。

在 Laravel 6.0 中使用了新的子查詢功能,比如要查詢全部目的地 destinations,以及抵達各目的地最后一班飛機的信息 name ,我們可以用單條語句這樣查詢:

return Destination::addSelect(['last_flight' => Flight::select('name') ->whereColumn('destination_id', 'destinations.id') ->orderBy('arrived_at', 'desc') ->limit(1) ])->get();

注意這里是怎么使用 Eloquent 來生成的子查詢。這樣的語法更好,更具有直觀表現力。同樣的,你也可以使用 query builder:

return Destination::addSelect(['last_flight' => function ($query) { $query->select('name') ->from('flights') ->whereColumn('destination_id', 'destinations.id') ->orderBy('arrived_at', 'desc') ->limit(1); }])->get();
 

“Order by” 子查詢

此外,Pull request #29563 使我們可以在查詢生成器的  orderBy() 方法中使用子查詢。繼續我們上面的示例,我們可以根據最后一班航班到達目的地的時間對目的地進行排序。

return Destination::orderByDesc( Flight::select('arrived_at') ->whereColumn('destination_id', 'destinations.id') ->orderBy('arrived_at', 'desc') ->limit(1) )->get();

與選擇一樣,您也可以直接使用查詢構建器來創建子查詢。 例如,您可能希望根據用戶的上次登錄日期訂購:

return User::orderBy(function ($query) { $query->select('created_at') ->from('logins') ->whereColumn('user_id', 'users.id') ->latest() ->limit(1); })->get();
 

“From” 子查詢

最后,Pull request #29602 使我們在查詢構造器中的  from() 使用子查詢成為可能。這些有時稱為派生表。

例如,你可能想要計算應用程序中用戶的平均捐贈總額。 但是,在 SQL 中,嵌套聚合函數是不可能的:

AVG(SUM(amount))

相反,我們可以使用 from 子查詢來計算它:

return DB::table(function ($query) { $query->selectRaw('sum(amount) as total') ->from('donations') ->groupBy('user_id'); }, 'donations')->avg('total');

你可能不需要每天都用到這個,但是當你確實需要它的時候,它是必不可少的。

如果您在 Laravel 之外使用 Eloquent,那么需要注意的一個突破性變化,在 Illuminate/Database/Capsule/Manager 對象上 table() 方法有明顯的改變。它已從表 table($table, $connection = null) 更改為表 table($table, $as = null, $connection = null)

 

了解更多

如果您有興趣了解更多關於子查詢和其他高級數據庫技術的信息,請務必關注我的博客,並觀看我的 Laracon US 2019 talk 演講。

在 Laracon,我還發布了一個新的視頻課程,我正在研究 Eloquent 的性能模式。本課程的目的是教 Laravel 開發人員如何把更多的工作推送到數據庫層來大幅提高 Laravel 應用程序的性能,同時仍然使用 Eloquent ORM。如果你感興趣的話,一定要加入郵件列表!

本文中的所有譯文僅用於學習和交流目的,轉載請務必注明文章譯者、出處、和本文鏈接
我們的翻譯工作遵照  CC 協議,如果我們的工作有侵犯到您的權益,請及時聯系我們。

原文地址:https://laravel-news.com/eloquent-subque...

譯文地址:https://learnku.com/laravel/t/33324


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM