1

こんばんは!

私は、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速?

ただ読んでくれてありがとう。ありがとう!

4

1 に答える 1

1

あなたがLaravelでやろうとしていることをほとんど解決し、コーナーケースのほとんどをカバーしているBaumを使うことができます。

于 2015-02-23T23:08:15.277 に答える