Je suis un peu coincé sur la manière de créer une requête efficace qui retourne les données de la structure EAV suivante.
Aujourd'hui, une table de produits existe déjà, contenant 4 champs fixes. Nous souhaitons mettre à niveau le système, permettant une quantité infinie de champs de produits supplémentaires, définis par le fabricant de chaque produit. Nous appelons ces champs supplémentaires 'Paramètres'.
Un paramètre peut être du type de données suivant:
Sur la base de cela, j'ai créé le modèle de base de données suivant:
:
J'ai besoin de créer une page Web dans ASP.NET C # qui affiche une liste de toutes les données de produit, y compris chaque paramètre défini avec sa valeur pour ce produit. Je dois être capable de filtrer la liste en recherchant n'importe quel champ/paramètre. Cette liste doit également être tritable sur n'importe quel champ/paramètre.
J'ai essayé de filtrer la liste par produit de jonction externe - ProductParameter - ProductParameTervalutuisitem - ParameTervaluLisitem Pour obtenir un résultat de la table contenant toutes les données, puis filtrant cette liste à l'aide d'une clause dynamique, construite et passée par l'application Web. Cela fonctionne lorsque vous recherchez sur 1 paramètre, mais lorsque vous commencez à rechercher plusieurs paramètres, vous obtenez des résultats incorrects car chaque paramètre est une ligne différente du résultat de la table et il n'y a tout simplement pas de paramètre A et B, car ils n'existe pas dans le même record (ligne).
Quelqu'un peut-il conseiller comment cela peut être atteint? La solution la plus parfaite serait 1 résultat de la table contenant toutes les données et chaque paramètre étant indiqué comme une colonne de la même ligne de produit. Est-ce trop complexe pour gérer au niveau de la base de données?
Merci de lire aussi loin. Tout conseil est le bienvenu.
Tout d'abord, ce que vous êtes sur le point de concevoir est probablement une très mauvaise idée. Une solution bien meilleure serait d'avoir un schéma dynamique sur lequel vous ajoutez de nouvelles tables et que vous avez la possibilité de comprendre comment interroger ces table (vous pouvez les placer dans un schéma). Cela évite largement tous les problèmes de plan de verrouillage et de requête que vous souhaitez rencontrer avec ce modèle. Il n'y a rien de mal avec les applications exécutées CREATE TABLE
maintenant et encore.
Deuxièmement, je ne suis pas sûr de comprendre pourquoi vous avez normalisé Parameter
dans sa propre table? Pourquoi ne pas mettre cela directement dans la table ManufacturerParameter
.
Troisièmement, si vous insistez sur la procédure avec votre modèle actuel, il existe des moyens d'atteindre ce que vous voulez (au moins si j'interprète votre exigence correctement). Ce que vous pouvez faire, c'est d'écrire votre requête de telle sorte qu'il s'agisse d'une résolution de l'argument de recherche lorsqu'il y a une correspondance, puis utilisez HAVING
pour filtrer les valeurs correspondantes. Je suppose que seul l'un des champs Text
, Boolean
, Datum
etc. est peuplé par un enregistrement ProductParameter
(vous voulez probablement appliquer cela avec une contrainte )
Par exemple, pour rechercher tous les produits qui ont un bolien = true pour un paramètre et texte = 'abc' pour un autre paramètre que vous pouvez faire:
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]
Si vous devez répertorier tous les paramètres de ce produit, vous pouvez utiliser le modèle de requête ci-dessus comme requête imbriquée et se joindre à ProductParameter
.
La requête ci-dessus peut être optimisée en maintenant une colonne calculée dans ProductParameter
qui présente une représentation de chaîne des différents types de données dans ce tableau. De cette façon, les états ci-dessus OR peuvent être réécrites comme une liste dans la liste (que vous voudrez passer comme paramètre de valorisation de la table).
Je voudrais répéter que ce que vous faites est probablement très mal. Si vous le faites, vous aurez probablement besoin d'accorder la plupart de vos plans de requête - l'optimiseur ne vous aidera plus. Et cela suppose que vous n'avez pas trop de variantes de requête, qui dirigeront votre cache de plan complète.
Quelqu'un peut-il conseiller comment cela peut être atteint? La solution la plus parfaite serait 1 résultat de la table contenant toutes les données et chaque paramètre étant indiqué comme une colonne de la même ligne de produit. Est-ce trop complexe pour gérer au niveau de la base de données?
Vous pouvez utiliser Dynamic SQL pour pivoter le EAV dans une table avec de nombreuses colonnes (soyez conscient de la limite de colonne de 1024) et d'avoir chaque produit sur une ligne. Je ne pense pas que cela fonctionnerait ainsi que la table indexée plus traditionnelle et la plus traditionnelle, mais vous pourriez essayer de concrétiser le résultat dans une table et de mettre des index à ce sujet.