2009-09-04 6 views
0

Bonjour à tous. Je vais poster la procédure stockée dans toute sa gloire. N'hésitez pas à déchirer en lambeaux. L'auteur ne m'en voudra pas.Ma requête T-SQL lente nécessite une refonte complète

DECLARE @itemTypeID INT 
SELECT @itemTypeID=ItemTypeID FROM dbo.ItemTypes WHERE ItemTypeName = 'Advert' 

BEGIN 
SELECT a.Active, 
    a.ParentClass, 
    a.Classification, 
    a.Variant, 
    FV."Full Views", 
    PV."Print Views", 
    EE."Email Enquiries", 
    a.ItemRef, 
    a.SiteID 
FROM 
(
SELECT DISTINCT i.ItemID, 
    i.ItemRef, 
    i.SiteID, 
    i.ParentClass, 
    i.Classification, 
    i.Summary AS "Variant",  
    i.Active 
FROM Items i 
JOIN Actions a 
ON a.ItemID = i.ItemID 
JOIN ActionTypes at 
ON a.ActionTypeID = at.ActionTypeID 
WHERE i.ItemTypeID = 1 
AND a.DateAndTime BETWEEN @startDate AND @endDate 
AND at.ActionTypeName IN ('Full view', 'Print view', 'Email enquiry') 
AND ((@siteID = -1) OR (i.SiteID = @siteID)) 
AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
AND ((@class = '%') OR (i.classification = @class)) 
) a LEFT JOIN 
(
SELECT i.ItemID, 
    COUNT(*) AS "Full Views" 
FROM CustomerSites cs JOIN Items i 
ON cs.SiteID = i.SiteID 
JOIN Actions a 
ON a.ItemID = i.ItemID 
JOIN ActionTypes at 
ON a.ActionTypeID = at.ActionTypeID 
JOIN Sites s 
ON cs.SiteID = s.SiteID 
WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
AND i.ItemTypeID = @itemTypeID 
AND at.ActionTypeName = 'Full view' 
AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
AND ((@class = '%') OR (i.classification = @class)) 
GROUP BY 
    i.ItemID 
) FV 
ON a.ItemID = FV.ItemID 
LEFT JOIN 
(
SELECT i.ItemID, 
    COUNT(*) AS "Print Views" 
FROM CustomerSites cs JOIN Items i 
ON cs.SiteID = i.SiteID 
JOIN Actions a 
ON a.ItemID = i.ItemID 
JOIN ActionTypes at 
ON a.ActionTypeID = at.ActionTypeID 
JOIN Sites s 
ON cs.SiteID = s.SiteID 
WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
AND i.ItemTypeID = @itemTypeID 
AND at.ActionTypeName = 'Print view' 
AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
AND ((@class = '%') OR (i.classification = @class)) 
GROUP BY 
    i.ItemID 
) PV 
ON a.ItemID = PV.ItemID 
LEFT JOIN 
(
SELECT i.ItemID, 
    COUNT(*) AS "Email Enquiries" 
FROM CustomerSites cs JOIN Items i 
ON cs.SiteID = i.SiteID 
JOIN Actions a 
ON a.ItemID = i.ItemID 
JOIN ActionTypes at 
ON a.ActionTypeID = at.ActionTypeID 
JOIN Sites s 
ON cs.SiteID = s.SiteID 
WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
AND i.ItemTypeID = @itemTypeID 
AND at.ActionTypeName = 'Email enquiry' 
AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
AND ((@class = '%') OR (i.classification = @class)) 
GROUP BY 
    i.ItemID 
) EE 
ON a.ItemID = EE.ItemID 
UNION 
SELECT '0','','','','','','','','' 

Maintenant, tout ce que cela fait est de retourner quelques enregistrements et le nombre de fois qu'une action particulière s'est produite contre eux.

Un petit sous-ensemble devrait ressembler.

Description de l'objet Vues imprimées Emails

Item1 Desc1 12 NULL 1 
Item2 Desc2 NULL NULL 3 
Item3 Desc3 5 6 2 

Espérons que vous pouvez voir ce qui se passe.

Je veux une liste d'éléments qui ont eu des actions les concernant pour une plage de dates particulière pour un client particulier pour un site particulier et la requête doit être filtrable sur la classe parente et la classification. Nice

La première sélection renvoie tous les éléments distincts qui correspondent aux critères de sélection.

Les 3 autres requêtes retournent simplement des comptages de 1 type d'action pour chaque élément. La requête est un pantalon lent même contre une petite quantité de données. Cela ne va jamais aller en direct, ça ne marchera pas.

Espérons que vous pouvez voir l'erreur des moyens 'auteurs' et le corriger.

+0

pouvez-vous réellement lire cette requête? IMO le style indent est horrible. –

+0

En bref, c'est 4 sous-requêtes jointes chanter JOINT GAUCHE – Robert

+0

@Robert: S'il vous plaît consulter la balise existante. J'ai changé la balise de "T-SQL" en "TSQL" – Sung

Répondre

3

Problèmes:

  1. requêtes de type "fourre-tout" ne peuvent pas être optimisés. Solution: SQL dynamique paramétré.
  2. L'UNION force le tri. Solution: utilisez plutôt UNION ALL (à moins que vous ayez vraiment besoin de DISTINCT implicite qu'il force).

Cela devrait être la solution la plus rapide:

DECLARE @sql AS VARCHAR(MAX) 

SELECT @sql = ' 
;WITH cteCommon as (
    SELECT 
     i.ItemID, 
     ,i.ItemRef 
     ,i.SiteID 
     ,i.ParentClass 
     ,i.Classification 
     ,i.Summary 
     ,i.Active 
     ,at.ActionTypeName 
    FROM Items    i 
     JOIN Actions  a ON a.ItemID = i.ItemID 
     JOIN ActionTypes at ON a.ActionTypeID = at.ActionTypeID 
    WHERE at.ActionTypeName IN (''Full view'', ''Print view'', ''Email enquiry'') 
     --NOTE: if you max-out this date range, then you mant want to exclude it also, RBarryYoung 
     AND a.DateAndTime BETWEEN @startDate AND @endDate 
     ' 
     + CASE @siteid WHEN -1 THEN '' ELSE 'AND (i.SiteID = @siteID) 
     ' END 
     + CASE @parentClass WHEN '%' THEN '' ELSE 'AND (i.ParentClass = @parentClass) 
     ' END 
     + CASE @class WHEN '%' THEN '' ELSE 'AND (i.classification = @class) 
     ' END 
     + ' 
) 
, cteA as (
    SELECT DISTINCT 
      i.ItemID, 
      ,i.ItemRef 
      ,i.SiteID 
      ,i.ParentClass 
      ,i.Classification 
      ,i.Summary AS "Variant" 
      ,i.Active 
     FROM cteA as i 
     WHERE i.ItemTypeID = 1 
) 
, cteCountViews AS (
    SELECT 
     i.ItemID 
     ,i.ActionType 
     ,COUNT(*) AS "ViewCount" 
    FROM cteCommon i 
     JOIN CustomerSites  cs ON cs.SiteID = i.SiteID 
     JOIN Sites    s ON cs.SiteID = s.SiteID 
    WHERE i.ItemTypeID = @itemTypeID 
     ' 
     + CASE WHEN @customerid IS NULL THEN '' ELSE '(cs.CustomerID = @customerID)' END 
     + ' 
    GROUP BY i.ItemID 
     ,i.ActionType 
    ) 
SELECT 
    a.Active 
    ,a.ParentClass 
    ,a.Classification 
    ,a.Variant 
    ,FV."Full Views" 
    ,PV."Print Views" 
    ,EE."Email Enquiries" 
    ,a.ItemRef 
    ,a.SiteID 
FROM cteA AS a 
LEFT JOIN (
     SELECT i.ItemID, ViewCount AS "Full Views" 
     FROM cteCountViews i 
     WHERE i.ActionTypeName = ''Full view'' 
    ) FV ON a.ItemID = FV.ItemID 
LEFT JOIN (
     SELECT i.ItemID, ViewCount AS "Print Views" 
     FROM cteCountViews i 
     WHERE i.ActionTypeName = ''Print view'' 
    ) PV ON a.ItemID = PV.ItemID 
LEFT JOIN (
     SELECT i.ItemID, ViewCount AS "Email Enquiries" 
     FROM cteCountViews i 
     WHERE i.ActionTypeName = ''Email enquiry'' 
    ) EE ON a.ItemID = EE.ItemID 
UNION ALL 
SELECT ''0'','''','''','''','''','''','''','''','''' 
' 
EXEC sp_ExecuteSQL @sql 
    ,'@startdate DATETIME,@enddate DATETIME,@siteid INT,@parentclass VARCHAR(MAX),@class VARCHAR(MAX),@itemtypeid INT,@customerid INT' 
    , @startdate, @enddate, @siteid, @parentclass, @class, @itemtypeid, @customerid 

Note: votre utilisation de caractères génériques sur certains Thes (classe, sites, etc.) JOIN est susceptible de causer une multiplication croisée de la source lignes et d'énormes ensembles de résultats.

+0

SQL dynamique ici nous allons. Je veux garder le syndicat car cela force la rangée vide à être la première.Merci – Robert

+0

Combien de lignes de sortie avez-vous? Le tri peut être coûteux pour les grands ensembles de lignes. – RBarryYoung

4

ici est la requête originale avec mon style de mise en forme:

SELECT 
    a.Active 
     ,a.ParentClass 
     ,a.Classification 
     ,a.Variant 
     ,FV."Full Views" 
     ,PV."Print Views" 
     ,EE."Email Enquiries" 
     ,a.ItemRef 
     ,a.SiteID 
    FROM (SELECT DISTINCT 
       i.ItemID, 
        ,i.ItemRef 
        ,i.SiteID 
        ,i.ParentClass 
        ,i.Classification 
        ,i.Summary AS "Variant" 
        ,i.Active 
       FROM Items    i 
        JOIN Actions  a ON a.ItemID = i.ItemID 
        JOIN ActionTypes at ON a.ActionTypeID = at.ActionTypeID 
       WHERE i.ItemTypeID = 1 
        AND a.DateAndTime BETWEEN @startDate AND @endDate 
        AND at.ActionTypeName IN ('Full view', 'Print view', 'Email enquiry') 
        AND ((@siteID = -1) OR (i.SiteID = @siteID)) 
        AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
        AND ((@class = '%') OR (i.classification = @class)) 
     ) a 
     LEFT JOIN (SELECT 
         i.ItemID 
          ,COUNT(*) AS "Full Views" 
         FROM CustomerSites   cs 
          JOIN Items    i ON cs.SiteID = i.SiteID 
          JOIN Actions    a ON a.ItemID = i.ItemID 
          JOIN ActionTypes  at ON a.ActionTypeID = at.ActionTypeID 
          JOIN Sites    s ON cs.SiteID = s.SiteID 
         WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
          AND i.ItemTypeID = @itemTypeID 
          AND at.ActionTypeName = 'Full view' 
          AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
          AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
          AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
          AND ((@class = '%') OR (i.classification = @class)) 
         GROUP BY i.ItemID 
       ) FV ON a.ItemID = FV.ItemID 
     LEFT JOIN (SELECT 
         i.ItemID 
          ,COUNT(*) AS "Print Views" 
         FROM CustomerSites  cs 
          JOIN Items   i ON cs.SiteID = i.SiteID 
          JOIN Actions   a ON a.ItemID = i.ItemID 
          JOIN ActionTypes at ON a.ActionTypeID = at.ActionTypeID 
          JOIN Sites   s ON cs.SiteID = s.SiteID 
         WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
          AND i.ItemTypeID = @itemTypeID 
          AND at.ActionTypeName = 'Print view' 
          AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
          AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
          AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
          AND ((@class = '%') OR (i.classification = @class)) 
         GROUP BY i.ItemID 
       ) PV ON a.ItemID = PV.ItemID 
     LEFT JOIN (SELECT 
         i.ItemID 
          ,COUNT(*) AS "Email Enquiries" 
         FROM CustomerSites cs 
          JOIN Items  i ON cs.SiteID = i.SiteID 
          JOIN Actions  a ON a.ItemID = i.ItemID 
          JOIN ActionTypes at ON a.ActionTypeID = at.ActionTypeID 
          JOIN Sites  s ON cs.SiteID = s.SiteID 
         WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
          AND i.ItemTypeID = @itemTypeID 
          AND at.ActionTypeName = 'Email enquiry' 
          AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
          AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
          AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
          AND ((@class = '%') OR (i.classification = @class)) 
         GROUP BY i.ItemID 
       ) EE ON a.ItemID = EE.ItemID 
UNION 
SELECT '0','','','','','','','','' 

cela devrait aider un peu:

;WITH CustomerSitesCounts AS 
(
SELECT 
    at.ActionTypeName 
     ,i.ItemID 
     ,COUNT(*) AS "Print Views" 
    FROM CustomerSites  cs 
     JOIN Items   i ON cs.SiteID = i.SiteID 
     JOIN Actions   a ON a.ItemID = i.ItemID 
     JOIN ActionTypes at ON a.ActionTypeID = at.ActionTypeID 
     JOIN Sites   s ON cs.SiteID = s.SiteID 
    WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
     AND i.ItemTypeID = @itemTypeID 
     AND at.ActionTypeName IN ('Print view','Full view','Email enquiry') 
     AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
     AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
     AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
     AND ((@class = '%') OR (i.classification = @class)) 
    GROUP BY at.ActionTypeName,i.ItemID 
) 
SELECT 
    a.Active 
     ,a.ParentClass 
     ,a.Classification 
     ,a.Variant 
     ,FV."Full Views" 
     ,PV."Print Views" 
     ,EE."Email Enquiries" 
     ,a.ItemRef 
     ,a.SiteID 
    FROM (SELECT DISTINCT 
       i.ItemID, 
        ,i.ItemRef 
        ,i.SiteID 
        ,i.ParentClass 
        ,i.Classification 
        ,i.Summary AS "Variant" 
        ,i.Active 
       FROM Items    i 
        JOIN Actions  a ON a.ItemID = i.ItemID 
        JOIN ActionTypes at ON a.ActionTypeID = at.ActionTypeID 
       WHERE i.ItemTypeID = 1 
        AND a.DateAndTime BETWEEN @startDate AND @endDate 
        AND at.ActionTypeName IN ('Full view', 'Print view', 'Email enquiry') 
        AND ((@siteID = -1) OR (i.SiteID = @siteID)) 
        AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
        AND ((@class = '%') OR (i.classification = @class)) 
     ) a 
     LEFT JOIN CustomerSitesCounts FV ON a.ItemID = FV.ItemID AND FV.ActionTypeName='Full view' 
     LEFT JOIN CustomerSitesCounts PV ON a.ItemID = PV.ItemID AND PV.ActionTypeName='Print view' 
     LEFT JOIN CustomerSitesCounts EE ON a.ItemID = EE.ItemID AND EE.ActionTypeName='Email enquiry' 
UNION 
SELECT '0','','','','','','','','' 
+0

Ça me semble bien, KM ... Je voudrais extraire cette partie Item/Actions/ActionTypes dans un CTE de base que les autres CTE et la requête principale partagent, éliminant encore code en double (n'affectera pas nécessairement le plan de requête, juste pour l'affichage). – richardtallent

+0

@KM: Mettez-vous les virgules au début des lignes uniquement pour le contrôle de la source (c'est-à-dire que l'ajout d'une colonne change 1 ligne au lieu de 2)? –

1

Tout d'abord, vous pouvez éviter d'avoir une copie de 3 absolument le même sous -les licences achètent un générique et utilisent l'instruction WITH pour que vous puissiez le réutiliser. Ensuite, pourquoi faire une sous-sélection quand ce n'est pas vraiment nécessaire.

Ensuite, supprimez certaines jointures (et donc DISTINCT) dont vous n'avez pas besoin.

Et vous obtenez quelque chose le long de ces lignes (non testé, naturellement):

DECLARE @itemTypeID INT 
SELECT @itemTypeID=ItemTypeID FROM dbo.ItemTypes WHERE ItemTypeName = 'Advert' 

BEGIN 
    WITH ItemTypeSummary 
    AS (SELECT i.ItemID, 
       at.ActionTypeName, 
       COUNT(*) AS CNT 
     FROM Items i 
     JOIN Actions a 
      ON a.ItemID = i.ItemID 
     JOIN ActionTypes at 
      ON a.ActionTypeID = at.ActionTypeID 
      AND at.ActionTypeName IN ('Full view', 'Print view', 'Email enquiry') 
     WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
      --// not sure you need those below as they are all part of Items filter anyways in the main query 
      /* 
      AND i.ItemTypeID = @itemTypeID 
      AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
      AND ((@siteID = -1) OR (cs.SiteID = @siteID)) 
      AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
      AND ((@class = '%') OR (i.classification = @class)) 
      */ 
     GROUP BY i.ItemID, 
        at.ActionTypeName 
    ) 

    SELECT DISTINCT i.ItemID, 
        i.ItemRef, 
        i.SiteID, 
        i.ParentClass, 
        i.Classification, 
        i.Summary AS "Variant", 
        i.Active, 
        FV.CNT AS "Full views", 
        PV.CNT AS "Print views", 
        EE.CNT AS "Email enquiries" 
    FROM  Items i 
    JOIN  CustomerSites cs 
      ON cs.SiteID = i.SiteID 
    LEFT JOIN ItemTypeSummary FV 
      ON i.ItemID = FV.ItemID 
      AND FV.ActionTypeName = 'Full view' 
    LEFT JOIN ItemTypeSummary PV 
      ON i.ItemID = PV.ItemID 
      AND PV.ActionTypeName = 'Print view' 
    LEFT JOIN ItemTypeSummary EE 
      ON i.ItemID = EE.ItemID 
      AND EE.ActionTypeName = 'Email enquiry' 

    WHERE i.ItemTypeID = @itemTypeID 
     AND ((@customerID IS NULL) OR (cs.CustomerID = @customerID)) 
     AND ((@siteID = -1) OR (i.SiteID = @siteID)) 
     AND ((@parentClass = '%') OR (i.ParentClass = @parentClass)) 
     AND ((@class = '%') OR (i.classification = @class)) 
END 

également garder à l'esprit que faire un tour du filtre ALL ou un élément spécifique que vous avez avec les OU déclarations ne sont pas vraiment cool si vous pouvez les éviter, car SQLServer ne sera pas capable de générer un plan d'exécution optimal.

+0

+1 pour le commentaire OU; briser cela en UNION de résultats multiples sans l'OR * pourrait * mieux fonctionner –

+0

Eh bien, c'est certainement différent. La raison pour laquelle les filtres ont été appliqués à la toute première sélection était de réduire le nombre d'articles retournés auxquels je me joignais. La requête ci-dessus renvoie cependant les éléments qui n'ont eu aucune action contre eux. Les éléments ci-dessus correspondent à chaque élément de la table d'éléments qu'un client particulier a déjà eu et pas seulement ceux qui ont eu une action dans la période. Je vais voir si je peux un peu modifier votre exemple. – Robert

+1

dans ItemTypeSummary, vos colonnes sélectionnées ne correspondent pas à vous groupe par colonne, ce qui entraînera une erreur –

1

Une autre option consiste à configurer une variable de table ou un #Table temporaire pour contenir les résultats. Ajouter une contrainte unique sur l'ItemID.

Séparez les sous-ensembles en étapes distinctes. Insérez d'abord les enregistrements que vous voulez compter dans cette table. Exécutez des UPDATE séparés sur les données pour chaque type d'affichage: UPDATE le nombre d'affichages d'impression, UPDATE le nombre d'affichages complets, UPDATE le nombre d'interrogations d'email. Puis renvoyez les résultats. Si nécessaire, divisez les conditions OU en requêtes distinctes.

Cette approche parcourt plusieurs fois vos données, mais elle évite les JOIN et les sous-requêtes qui ne sont pas indexées.

Dans notre application, avoir plusieurs étapes semble mieux performer qu'une requête très complexe. Vos résultats peuvent varier.

+0

Malheureusement les tables temporaires n'ont pas amélioré la performance à un bon niveau mais c'était une amélioration. Aller à l'option SQL dynamique. – Robert

1

Réécriture:

WITH base AS (
    SELECT i.ItemID, 
     i.ItemRef, 
     i.SiteID, 
     i.ParentClass, 
     i.Classification, 
     i.Summary, 
     i.Active, 
     i.ItemTypeID, 
     at.ActionTypeName 
    FROM ITEMS i 
    JOIN ACTIONS a ON a.ItemID = i.ItemID 
    JOIN ACTIONTYPES at ON at.ActionTypeID = a.ActionTypeID 
    WHERE a.DateAndTime BETWEEN @startDate AND @endDate 
    AND (@siteID = -1 OR i.SiteID = @siteID) 
    AND (@parentClass = '%' OR i.ParentClass = @parentClass) 
    AND (@class = '%' OR i.classification = @class)), 
    items AS (
    SELECT b.ItemID, 
      b.ItemRef, 
      b.SiteID, 
      b.ParentClass, 
      b.Classification, 
      b.Summary AS "Variant", 
      b.Active 
     FROM base b 
    WHERE b.itemtypeid = 1 
     AND b.actiontypename IN ('Full view', 'Print view', 'Email enquiry') 
    GROUP BY i.ItemID, i.ItemRef, i.SiteID, i.ParentClass, i.Classification, i.Summary, i.Active), 
    full_views AS (
    SELECT b.ItemID, 
      COUNT(*) AS num_full_Views 
     FROM base b 
     JOIN CUSTOMERSITES cs ON cs.siteid = b.siteid 
     JOIN SITES s ON s.siteid = b.siteid 
    WHERE b.itemtypeid = @itemTypeID 
     AND b.ActionTypeName = 'Full view' 
     AND (@customerID IS NULL OR cs.CustomerID = @customerID) 
    GROUP BY b.itemid), 
    print_views AS (
    SELECT b.ItemID, 
      COUNT(*) AS num_print_views 
    FROM base b 
    JOIN CUSTOMERSITES cs ON cs.siteid = b.siteid 
    JOIN SITES s ON s.siteid = b.siteid 
    WHERE b.itemtypeid = @itemTypeID 
     AND b.ActionTypeName = 'Print view' 
     AND (@customerID IS NULL OR cs.CustomerID = @customerID) 
GROUP BY b.itemid), 
    email_queries AS (
SELECT b.ItemID, 
     COUNT(*) AS num_email_enquiries 
    FROM base b 
    JOIN CUSTOMERSITES cs ON cs.siteid = b.siteid 
    JOIN SITES s ON s.siteid = b.siteid 
WHERE b.itemtypeid = @itemTypeID 
     AND b.ActionTypeName = 'Email enquiry' 
     AND (@customerID IS NULL OR cs.CustomerID = @customerID) 
    GROUP BY b.itemid) 
    SELECT a.Active, 
      a.ParentClass, 
      a.Classification, 
      a.Variant, 
      ISNULL(fv.num_full_Views, 0) AS "Full Views", 
      ISNULL(pv.num_print_views, 0) AS "Print Views", 
      ISNULL(ee.num_email_enquiries, 0) AS "Email Enquiries", 
      a.ItemRef, 
      a.SiteID 
    FROM items a 
LEFT JOIN full_views fv ON fv.itemid = a.itemid 
LEFT JOIN print_views pv ON pv.itemid = a.itemid 
LEFT JOIN email_queries ee ON ee.itemid = a.itemid 

Pour obtenir de meilleures performances, je voudrais convertir ce SQL dynamique afin de supprimer les contrôles des paramètres comme ceux-ci:

AND (@siteID = -1 OR i.SiteID = @siteID) 

... à cause du négatif impact sur sargability.

+0

Travailler sur cette conversion maintenant comme il va merci. – Robert

Questions connexes