簡體   English   中英

cakephp4中的聯合請求和分頁

[英]union request and pagination in cakephp4

我提出了兩個要求。 第一個給了我 2419 個結果,我將結果存儲在 $requestFirst 中。 第二個,1 個結果,我將結果存儲在 $requestTwo 中。 我做一個工會:

$requestTot = $requestFirst->union($requestTwo);

$requestTot 的總數是 2420 個結果,所以到目前為止一切都很好。 然后:

$request = $this->paginate($requestTot);
$this->set(compact('request'));

在這里我不明白,在分頁的每一頁上我都找到了$requestTwo 的結果。 此外,分頁顯示我:

Page 121 of 121, showing 20 record(s) out of 2,420 total

這是正確的結果數,但當我將每頁的結果數乘以頁數時得到 2540。這是結果總數加上每頁一個。

誰能解釋一下?

Debug Kit的 SQL 面板中檢查生成的 SQL,您應該看到LIMITOFFSET子句是在第一個查詢上設置的,而不是作為全局子句附加的,因此它們會影響聯合查詢。

它看起來像這樣:

(SELECT id, title FROM a LIMIT 20 OFFSET 0)
UNION
(SELECT id, title FROM b)

那么接下來會發生什么,分頁將只應用於$requestFirst查詢,並且$requestTwo查詢每次都會在它之上聯合,因此你會在每一頁上看到它的結果。

此當前限制的解決方法是使用聯合查詢作為子查詢或從中獲取結果的公用表表達式。 為了使其工作,您需要確保選擇聯合查詢的字段時沒有別名! 這可以通過使用Table::subquery()來實現:

$requestFirst = $this->TableA
    ->subquery()
    ->select(['a', 'b'])
    // ...

$requestTwo = $this->TableB
    ->subquery()
    ->select(['c', 'd'])
    // ...

或者通過顯式選擇別名等於列名的字段:

$requestFirst = $this->TableA
    ->find()
    ->select(['a' => 'a', 'b' => 'b'])
    // ...

$requestTwo = $this->TableB
    ->find()
    ->select(['c' => 'c', 'd' => 'd'])
    // ...

然后您可以安全地將這些查詢用於聯合作為子查詢:

$union = $requestFirst->union($requestTwo);

$wrapper = $this->TableA
    ->find()
    ->from([$this->TableA->getAlias() => $union]);

$request = $this->paginate($wrapper);

或作為公用表表達式(如果您的 DBMS 支持它們):

$union = $requestFirst->union($requestTwo);

$wrapper = $this->TableA
    ->find()
    ->with(function (\Cake\Database\Expression\CommonTableExpression $cte) use ($union) {
        return $cte
            ->name('union_source')
            ->field(['a', 'b'])
            ->query($union)
    })
    ->select(['a', 'b'])
    ->from([$this->TableA->getAlias() => 'union_source']);

$request = $this->paginate($wrapper);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM