Je travaille actuellement sur un cas d'utilisation particulièrement complexe. Simplification ci-dessous :)Performance des sous-requêtes Sql fonctions
Tout d'abord, un enregistrement client a une relation plusieurs-à-un avec une collection de services, c'est-à-dire qu'un seul client peut avoir plusieurs services associés.
Dans mon déclencheur, j'écris une requête qui renvoie l'identifiant d'un client en fonction de certains critères. Les critères sont les suivants,
- Si au moins un service est de type B, et aucun service de type A existent, id retour
- Si au moins un service est de type C, et aucun service de type B ou a existent, id retour
- Si au moins un service est de type D, et aucun service de type C ou B ou a existent, id retour
et mon approche actuelle est de former une requête similaire à celui ci-dessous
SELECT c.ClientId
FROM
Clients AS c
-- actually INNER JOIN is superfluous in this sample, but required for
-- other auxilliary criteria i have left out. illustrates relationship
-- between Clients and Services table
INNER JOIN Services AS s ON c.ClientId = s.ClientId
WHERE
-- has at least one service of type B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A'))) OR
-- has at least one service of type C, no B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A'))) OR
-- has at least one service of type D, no C, no B, no A
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'D')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) AND
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A')))
où [dbo].[Get_ServicesByClientIdAndType]
est une fonction qui renvoie des services associés pour l'ID client et le type de service spécifiés. Similaire à
-- this query is actually significantly more complex than shown
-- below, but this illustrates use of parameters client id and
-- service type
SELECT s.ServiceType
FROM
Services AS s
WHERE
s.ClientId = @clientId AND
s.ServiceType = @serviceType
supposer que ce soit un moyen optimal d'exprimer ce cas d'utilisation, fonctionneraient [dbo].[Get_ServicesByClientIdAndType]
sous-requête mise en cache ou ne changeant le paramètre de service nécessite une nouvelle évaluation chaque appel? [J'invoque cette chose comme 9 fois !!! Sql Server 2005]
Je sais que Sql Server 2005 prend en charge certaines optimisations de sous-requêtes, comme les résultats de mise en cache, mais je ne sais pas avec certitude dans quelles circonstances ou comment former mes sous-requêtes [ou fonctions] telles que Je profite au maximum des capacités de Sql Server.
EDIT: examiné mes critères ci-dessus, et ne pouvait pas laisser aller d'une chose lancinante sentiment était éteint. J'ai joué avec une certaine logique dans ma tête, et est venu avec cette [plus simple] formulation
SELECT c.ClientId
FROM
Clients AS c
INNER JOIN Services AS s ON c.ClientId = s.ClientId
WHERE
NOT EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'A')) AND
(EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'B')) OR
EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'C')) OR
EXISTS (SELECT * FROM Get_ServicesByClientIdAndType (c.ClientId, 'D')))
essentiellement, il existe pas de scénario impliquant B qui conduirait à un rejet, de même pour C et D, de sorte que toute configuration est acceptable. nous nous soucions seulement que A n'est présent dans aucune sélection. Arg! Charlie Brown!
laissant les deux expressions pour examen, et je reste très bien apprécier les réponses concernant les performances utilisateur WRT SQL Server fonctions définies.
Wow, très cool. Cela a du sens, en tabulant essentiellement les occurrences dans une seule sous-requête, puis en sélectionnant celles-ci. J'ai seulement reformulé mes critères dans une expression plus simple mais équivalente - le seul effet sur votre solution est une clause WHERE externe plus simple 'WHERE A.ServiceA = 0 ET (A.ServiceB> 0 OU A.ServiceC> 0 OU A.ServiceD> 0) ' –