2009-09-28 13 views
1

En raison d'une variété de décisions de conception, nous avons une table, 'CustomerVariable'. CustomerVariable a trois bits d'information - son propre identifiant, un identifiant à variable (une liste de paramètres possibles que le client peut avoir), et la valeur de cette variable. D'autre part, la table Variable contient les informations sur une valeur par défaut - dans le cas où la variable CustomerVariable n'est pas définie. Cela fonctionne bien dans la plupart des situations, ce qui nous permet de ne pas avoir à créer une liste d'informations incroyablement longue - en particulier dans le cas où 16 variables similaires doivent être gérées pour un client.Accélération d'une requête SQL avec des informations de données génériques

Le problème vient en essayant d'obtenir cette information dans un select. Jusqu'à présent, notre «meilleure» solution implique beaucoup trop de jointures pour être efficace - nous obtenons une liste des 16 VariableIds dont nous avons besoin d'informations, en les plaçant dans des variables, d'abord. Par la suite, cependant, nous devons faire:

CROSS JOIN dbo.Variable v01 
    LEFT JOIN dbo.CustomerVariable cv01 ON cv01.customerId = c.id 
             AND cv01.variableId = v01.id 
    CROSS JOIN dbo.Variable v02 
    LEFT JOIN dbo.CustomerVariable cv02 ON cv02.customerId = c.id 
             AND cv02.variableId = v02.id 
    -- snip -- 
    CROSS JOIN dbo.Variable v16 
    LEFT JOIN dbo.CustomerVariable cv16 ON cv16.customerId = c.id 
             AND cv16.variableId = v16.id 
WHERE 
    v01.id = @cv01VariableId 
    v02.id = @cv02VariableId 
    -- snip -- 
    v16.id = @cv16VariableId 

Je sais qu'il doit y avoir une meilleure façon, mais nous ne pouvons pas sembler le trouver au milieu temps de crise. Toute aide serait grandement appréciée.

+1

Comment déterminez-vous qu'il y a trop de jointures pour être efficace? –

+1

ce qui est avec les CROIX JOINS? montrer plus de la requête! –

+0

@rexem: Je pense que 16 auto se qualifie. ;) – NotMe

Répondre

3

Si votre ensemble de données est relativement petit et pas trop volatile, vous pouvez utiliser des vues matérialisées (en supposant que votre base de données les supporte) pour optimiser la recherche.

Si les vues matérialisées ne sont pas une option, ne pas creer une procédure stockée qui récupère les données en deux passes:

  1. d'abord récupérer tous les CustomerVariables disponibles pour un client particulier (ou un ensemble de clients)
  2. Ensuite, récupérez toutes les valeurs par défaut de la table Variables
  3. Effectuez une union non distincte sur les résultats en fusionnant les valeurs par défaut là où un enregistrement CustomerVariable est manquant.

Essentiellement, il est l'équivalent de:

SELECT variableId, 
     CASE WHEN CV.variableId = NULL THEN VR.defaultValue ELSE CV.value END 
FROM Variable VR 
LEFT JOIN CUstomerVariable CV on CV.variableId = VR.variableId 
WHERE CV.customerId = c.id 
+0

Incidemment, je suis allé deux routes (le mien décrit ci-dessus, et celui-ci). Il y a de bonnes choses et de mauvaises choses pour les deux. Avec la méthode à deux passes, vous pouvez réellement répondre plus rapidement au navigateur et terminer facilement la boucle pour obtenir les données si l'utilisateur le souhaite; cependant, la durée totale de la requête est plus lente. Avec la route d'affichage, il est plus facile de donner un accès direct aux requêtes pour d'autres applications. – NotMe

1

Le type de requête que vous voulez est appelée une requête pivot table ou crosstab.

La manière la plus simple de résoudre ce problème est de créer une vue basée sur une requête de tableau croisé. Cela retournera les colonnes d'être vertical à être horizontal comme une table sql régulière. Une fois cela fait, interrogez simplement la vue. Facile. ;)

Questions connexes