国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Laravel Query Builder 復(fù)雜查詢案例:子查詢實(shí)現(xiàn)分區(qū)查詢 partition b

littleGrow / 3038人閱讀

摘要:案例案例在文章列表中附帶上前條評論,在獲取文章列表時(shí)同時(shí)把每個(gè)文章的前條評論一同查詢出來。這是典型分區(qū)查詢案例,需要根據(jù)表中的字段進(jìn)行分區(qū),同時(shí)根據(jù)條件進(jìn)行排序,把符合條件的前條是數(shù)據(jù)取出來。查詢語句中定義變量以及函數(shù)的使用如何構(gòu)建子查詢。

案例

案例:Laravel 在文章列表中附帶上前10條評論?,在獲取文章列表時(shí)同時(shí)把每個(gè)文章的前10條評論一同查詢出來。

這是典型分區(qū)查詢案例,需要根據(jù) comments 表中的 post_id 字段進(jìn)行分區(qū),同時(shí)根據(jù)條件進(jìn)行排序,把符合條件的前 N 條是數(shù)據(jù)取出來。

在其他數(shù)據(jù)庫(Oracle, SQL Server,Vertica) 包含了 row_number partition by 這樣的函數(shù),能夠比較容易的實(shí)現(xiàn)。

比如在 SQL Server 中:

SELECT * FROM (
SELECT *, row_number() OVER (partition by post_id ORDER BY created_at desc) rank FROM comments where post_id in (1,2,3,4,5) 
) b where rand < 11;

在 mysql 中要復(fù)雜一些,我們先來看看上面案例中實(shí)現(xiàn)需求的幾種解決辦法。

解決辦法 方法1:

在 blade 中要顯示評論數(shù)據(jù)的地方 post->comments()->limit(10)

問題:如果取了 20 條 Post 數(shù)據(jù),就會有 20 條取 comments 的 sql 語句,會造成執(zhí)行的 sql 語句過多。

不是非??扇。饕獑栴}會造成 SQL 語句過多,對數(shù)據(jù)庫服務(wù)器產(chǎn)生壓力,不過這里可以使用緩存來改進(jìn),但是不在本文章討論范圍里。

方法2:

直接通過 with 把 Post 的所有 comments 數(shù)據(jù)都取出來,在 blade 中 post->comments->take(10)

問題:Laravel 會預(yù)先把文章所有的評論數(shù)據(jù)查詢出來,如果文章的評論數(shù)據(jù)非常多,可能會造成內(nèi)存泄漏。
方法3:
$posts = Post::paginate(15);

$postIds = $posts->pluck("id")->all();

//找出符合條件的 comments ,同時(shí)定義 @post, @rank 變量,這里沒有用 all,get 等函數(shù),此時(shí)并不會執(zhí)行 SQL 語句。
$sub = Comment::whereIn("post_id",$postIds)->select(DB::raw("*,@post := NULL ,@rank := 0"))->orderBy("post_id");

//把上面構(gòu)造的 sql 查詢作為子表進(jìn)行查詢,根據(jù) post_id 進(jìn)行分區(qū)的同時(shí) @rank 變量不斷+1
$sub2 = DB::table( DB::raw("({$sub->toSql()}) as b") )
            ->mergeBindings($sub->getQuery())
            ->select(DB::raw("b.*,IF (
            @post = b.post_id ,@rank :=@rank + 1 ,@rank := 1
        ) AS rank,
        @post := b.post_id"));

//取出符合條件的前10條comment
$commentIds = DB::table( DB::raw("({$sub2->toSql()}) as c") )
            ->mergeBindings($sub2)
        ->where("rank","<",11)->select("c.id")->pluck("id")->toArray();

$comments = Comment::whereIn("id",$commentIds)->get();

$posts = $posts->each(function ($item, $key) use ($comments) {
    $item->comments = $comments->where("post_id",$item->id);
});
會產(chǎn)生三條sql
select * from `posts` limit 15 offset 0;

select `c`.`id` from (select b.*,IF (
@post = b.post_id ,@rank :=@rank + 1 ,@rank := 1
) AS rank,
@post := b.post_id from (select *,@post := NULL ,@rank := 0 from `comments` where `post_id` in ("2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16") order by `post_id` asc) as b) as c where `rank` < "11";

select * from `comments` where `id` in ("180", "589", "590", "3736");
知識點(diǎn)

toSql() 方法的作用是為了獲取不帶有 binding 參數(shù)的 SQL, 也就是說帶問號的 SQL

getQuery() 方法的作用是為了獲取 binding 參數(shù)并代替 toSql() 獲得SQL的問號,從而得到完整的SQL

raw() 的作用是直接把 SQL 套進(jìn) Laravel 的查詢構(gòu)造器中。

mysql 查詢語句中定義變量 @post := NULL ,@rank := 0 以及 IF 函數(shù)的使用

如何構(gòu)建子查詢。

為什么不直接用原生 SQL 語句來實(shí)現(xiàn)?

這里之所以堅(jiān)持使用 Laravel Query Builder 來實(shí)現(xiàn),可以有效防止 SQL 注入,并且和 ORMModel 對象關(guān)聯(lián)起來。

如果大家還有更多類似這種復(fù)雜的需求,歡迎大家投稿。
討論交流

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/28136.html

相關(guān)文章

  • Laravel核心解讀--Database(四) 模型關(guān)聯(lián)

    摘要:為關(guān)聯(lián)關(guān)系設(shè)置約束子模型的等于父模型的上面設(shè)置的字段的值子類實(shí)現(xiàn)這個(gè)抽象方法通過上面代碼看到創(chuàng)建實(shí)例時(shí)主要是做了一些配置相關(guān)的操作,設(shè)置了子模型父模型兩個(gè)模型的關(guān)聯(lián)字段和關(guān)聯(lián)的約束。不過當(dāng)查詢父模型時(shí),可以預(yù)加載關(guān)聯(lián)數(shù)據(jù)。 Database 模型關(guān)聯(lián) 上篇文章我們主要講了Eloquent Model關(guān)于基礎(chǔ)的CRUD方法的實(shí)現(xiàn),Eloquent Model中除了基礎(chǔ)的CRUD外還有一個(gè)...

    gekylin 評論0 收藏0
  • 寫一個(gè)“特殊”的查詢構(gòu)造器 - (四、條件查詢復(fù)雜條件)

    摘要:復(fù)雜的條件在的條件查詢中,不只有這些基本的子句,還有等復(fù)雜一些的子句。這篇我們就來講一下查詢構(gòu)造器如何構(gòu)造這些復(fù)雜的查詢語句。 復(fù)雜的條件 在 SQL 的條件查詢中,不只有 where、or where 這些基本的子句,還有 where in、where exists、where between 等復(fù)雜一些的子句。而且即使是 where 這種基礎(chǔ)的子句,也有多個(gè)條件的多種邏輯組合。這篇...

    baoxl 評論0 收藏0
  • Oceanbase新版本復(fù)合分區(qū)添加分區(qū)操作

    Oceanbase新版本復(fù)合分區(qū)添加分區(qū)操作 img{ display:block; margin:0 auto !important; width:100%; } body{ width:75%; ...

    不知名網(wǎng)友 評論0 收藏2700
  • 20 個(gè) Laravel Eloquent 必備的實(shí)用技巧

    摘要:看起來是一個(gè)簡單的機(jī)制,但是在底層,有很多半隱藏的函數(shù)和鮮為人知的方式來實(shí)現(xiàn)更多功能。在這篇文章中,我將演示幾個(gè)小技巧。另外,在里也有些和時(shí)間相關(guān)的預(yù)定義方法通過關(guān)系排序一個(gè)復(fù)雜一點(diǎn)的技巧。幸運(yùn)的是,確實(shí)有這樣的方法。 showImg(https://segmentfault.com/img/bV8L5s?w=1240&h=634); Eloquent ORM 看起來是一個(gè)簡單的機(jī)制,...

    clasnake 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<