こんばんは!
私は、Laravel が MySQL Nested Set Model (lft および rgt キー) に基づくリレーションシップを持つことを可能にするパッケージに取り組んでいます。
凡例: X、Y、Z、A、B、C は整数です。
これを eshop カテゴリで使用すると仮定しましょう。
私の最初のタスクは、親子関係を作成することです。現在のカテゴリの親を見つけるリレーションを作成できました。私のクエリは次のようになります。
select * from categories where lft < X and rgt > Y order by lft limit 1
これは完全に正しく機能します。しかし、たとえば 100 個のカテゴリを読み込もうとすると問題が発生します。次に、100 のカテゴリに対する 1 つの SQL クエリです。
select * from categories limit 100
各カテゴリの親に対する 1 つの SQL クエリ:
select * from categories where lft < X and rgt > Y order by lft desc limit 1
つまり、合計で101の SQL クエリです。
ここが問題の部分です。Eager Loading (すべての関係クエリを 1 つのクエリにマージする) と呼ばれる手法を使用したいと考えています。しかし、それを行う方法は?
ソリューション番号 1
私の最初の解決策は、次からすべての lft および rgt キーを収集することでした。
select * from categories limit 100
次のようなクエリを作成します。
select * from categories where (lft < X or lft < Y or lft < Z ...)
and ( rgt > A or rgt > B or rgt > C ...) order by lft desc
しかし、この解決策はまったく機能しません。カテゴリのすべての親を返します。
ソリューション番号 2
そこで、この方法でちゃんと動くようにしてみました。元のクエリは同じように見えます。
select * from categories limit 100
しかし、親のロードはまったく異なります。
(select * from categories where lft < X and rgt > Y order by lft desc limit 1)
union all
(select * from categories where lft < A and rgt > B order by lft desc limit 1)
union all...
このクエリは関連する結果のみを返しますが、これは完璧ですが、親をその子に追加するには、元のクエリのすべての結果を foreach サイクルで (PHP 側で) 実行する必要があります (カテゴリ制限 100 から * を選択)。その foreach 内で、(元のクエリから) すべての親を反復する別の foreach を実行する必要があり、2 番目の foreach 内には、10 000 (100 * 100) サイクルと比較 = looooooooong 実行を行う比較ロジックがあります。
ソリューション番号 3
そこで、別の解決策を考えました。これが私の意見では最善です。これは、2 番目のソリューションの単なる改善です。
元のクエリ:
select * from categories limit 100
関係クエリ:
(select categories.*, X as child_lft, Y as child_rgt from categories
where lft < X and rgt > Y order by lft desc limit 1)
union all
(select categories.*, A as child_lft, B as child_rgt from categories
where lft < A and rgt > B order by lft desc limit 1)
union all...
これで、PHP 側には、元のクエリの結果 (100 項目) を含む 1 つの配列と、リレーション クエリの結果 (100 項目) を含む配列があります。改善されたのは、すべての親の結果に、それを要求したカテゴリの lft および rgt キー (child_lft および child_rgt) が含まれるようになったことです。現在、PHP スクリプトははるかに高速です。最初に、すべての親を含む新しい配列 ($parents と名付けましょう) を作成します。すべての項目キー ($parents の値のキー) は、それを要求したカテゴリを識別するコード (child_lft.child_rgt => 1.5) です。これは 100 回反復する foreach です。2 番目の foreach は、元のクエリの結果を繰り返し処理し、$parents 配列にその lft および rgt キーに適合するキーを持つ値が含まれているかどうかを確認します。したがって、さらに 100 回繰り返します。合計 200 回の反復 = 完璧です。しかし、「関係クエリ」
それで、それを行う別の方法はありますか?または、ソリューションで私のSQLクエリを作成する方法はありますか? 3速?
ただ読んでくれてありがとう。ありがとう!