次のEAV構造のデータを返す効率的なクエリを作成する方法にちょっとこだわっています。
現在、4つの固定フィールドを含む製品テーブルがすでに存在しています。システムをアップグレードして、各製品の製造元が定義した追加の製品フィールドを無制限に許可したいと考えています。これらの追加フィールドを「パラメーター」と呼びます。
パラメータは、次のデータ型にすることができます。
これに基づいて、次のデータベースモデルを作成しました。
:
ASP.NET C#でWebページを構築する必要があります。これには、定義された各パラメーターとその製品の値を含む、すべての製品データのリストが表示されます。任意のフィールド/パラメーターを検索してリストをフィルターできるようにする必要があります。このリストは、どのフィールド/パラメーターでもソート可能である必要があります。
Product-ProductParameter-ProductParametervalueListItem-ParameterValueListItemを外部結合してリストをフィルタリングし、すべてのデータを含むテーブル結果を取得してから、動的なwhere句を使用してそのリストをフィルタリングし、Webアプリによって作成およびパススルーされました。これは1つのパラメーターで検索すると機能しますが、複数のパラメーターで検索を開始すると、各パラメーターがテーブル結果の異なる行であり、パラメーターAとBの間に「AND」一致がないため、誤った結果が得られます。同じレコード(行)に存在しない。
誰かがこれをどのように達成できるか私にアドバイスできますか?最も完璧なソリューションは、すべてのデータと各パラメーターが同じ製品行の列として表示されている1つのテーブル結果です。これはデータベースレベルで処理するには複雑すぎますか?
ここまで読んでいただきありがとうございます。どんなアドバイスでも大歓迎です。
まず第一に、設計しようとしているのはおそらく非常に悪い考えです。より良い解決策は、新しいテーブルを追加し、アプリケーションにそれらのテーブルのクエリ方法を理解させる動的スキーマを用意することです(それらをスキーマに配置できます)。これにより、このモデルで発生する可能性のあるすべてのロックおよびクエリプランの問題が大幅に回避されます。 CREATE TABLE
を繰り返し実行するアプリケーションに問題はありません。
第二に、Parameter
を独自のテーブルに正規化した理由が理解できませんか?それをManufacturerParameter
テーブルに直接入れてみませんか。
第3に、現在のモデルの続行を主張する場合、(少なくとも私が要件を正しく解釈している場合は)希望どおりの方法を実現する方法があります。何ができるかは、一致がある場合に検索引数を合計するようにクエリを記述し、HAVING
を使用して一致する値を除外することです。フィールドText
、Boolean
、Datum
などの1つだけがProductParameter
レコードごとに入力されると想定しています(おそらく、これを制約付きで強制したいでしょう) )
たとえば、1つのパラメーターがbolean = trueで、他のパラメーターがtext = 'abc'であるすべての製品を検索するには、次のようにします。
SELECT P.Name
FROM Product P
JOIN ProductParameter PP
WHERE P.ID = Foo
AND PP.Boolean = 1 OR PP.Text = 'abc' ... /* For each filter */
GROUP BY P.Name /* And any other things you want out of product */
HAVING COUNT(*) >= [Number of where clauses]
この製品のすべてのパラメーターをリストする必要がある場合は、上記のクエリテンプレートをネストされたクエリとして使用し、ProductParameter
に結合して戻すことができます。
上記のクエリは、そのテーブルのさまざまなデータ型の文字列表現を持つProductParameter
の計算列を維持することで最適化できます。このようにして、上記のORステートメントは、INリスト(テーブル値パラメーターとして渡す必要があります)として書き直すことができます)。
繰り返しますが、あなたがしていることはおそらく非常に間違っています。それを行う場合は、ほとんどのクエリプランを手動で調整する必要があります。オプティマイザはもう役に立ちません。また、クエリバリアントが多すぎず、プランのキャッシュがいっぱいになることが想定されています。
誰かがこれをどのように達成できるか私にアドバイスできますか?最も完璧なソリューションは、すべてのデータと各パラメーターが同じ製品行の列として表示されている1つのテーブル結果です。これはデータベースレベルで処理するには複雑すぎますか?
動的SQLを使用して、EAVを多数の列を持つテーブルにピボットし(列の制限は1024に注意してください)、各製品を1行に配置できます。これは、従来のタイトなインデックス付きテーブルほどパフォーマンスが良いとは思いませんが、結果セットをテーブルに具体化して、それにインデックスを付けることができます。