2009-09-25 5 views
0

Je dois créer une commission de vente & rapportRapport de synthèse regroupé à la date de plusieurs plages

Fondamentalement, il va (s'il vous plaît pardonnez la folie blatent de la table SaleDate, mais je simplifie la logique métier, et en réalité est logique de l'avoir de cette façon)

SELECT agentName, 
     SUM(sales.Amount) AS Gross, 
     SUM(sales.Amount * sales.Commission) AS Commission 
FROM agent 
    INNER JOIN sales ON agent.agentId = sales.agentId 
WHERE sales.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate AND @maxDate) 
GROUP BY agentName 

Cette requête fonctionne donc très bien. Le problème se produit lorsque j'ai besoin d'ajouter une deuxième plage de dates.

IE, où ils veulent comparer les ventes de 2007 & Les ventes de 2008 côte à côte.

Je actuellement ont essentiellement la même requête, mais j'ai ajouté des alias à la table de vente et a ajouté un autre

SELECT agentName, 
     SUM(sales1.Amount) AS Gross1, 
     SUM(sales1.Amount * sales1.Commission) AS Commission1, 
     SUM(sales2.Amount) AS Gross2, 
     SUM(sales2.Amount * sales2.Commission) AS Commission2, 
     SUM(sales3.Amount) AS Gross3, 
     SUM(sales3.Amount * sales3.Commission) AS Commission3 
FROM agent 
    INNER JOIN sales1 ON agent.agentId = sales1.agentId 
    INNER JOIN sales2 ON agent.agentId = sales2.agentId 
    INNER JOIN sales3 ON agent.agentId = sales3.agentId 
WHERE sales1.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1) OR 
     sales2.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate2 AND @maxDate2) OR 
     sales3.saleId IN (SELECT saleId FROM saleDate WHERE saleDate.myDate BETWEEN @minDate3 AND @maxDate3) 
GROUP BY agentName 

Cette requête prend toujours cependant (plus de 20 minutes avant que j'annulé il), la l'original a pris moins d'une seconde et si je n'utilise que deux groupes cela prend 9 secondes.

Des idées sur la façon d'améliorer cette performance?

Je suis prêt à changer la conception de cette requête.

Répondre

1

Si votre première requête fonctionne bien, pourquoi ne pas simplement l'UNION ALL avec les nouvelles dates subbed dans la 2ème version? Oui, vous n'obtiendrez pas de sortie pivotée, mais c'est assez facile à corriger avec le code de présentation de la couche application.

Une autre option serait d'utiliser CASE.

SELECT agentName, 
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate1 AND @maxDate1 THEN sales.Amount ELSE 0 END) AS Gross1, 
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate1 AND @maxDate1 THEN sales.Commission ELSE 0 END) AS Commission1, 
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate2 AND @maxDate2 THEN sales.Amount ELSE 0 END) AS Gross2, 
SUM (CASE WHEN saleDate.myDate BETWEEN @minDate2 AND @maxDate2 THEN sales.Commission ELSE 0 END) AS Commission2 
FROM agent 
INNER JOIN sales ON agent.agentId = sales.agentId 
GROUP BY agentName 
+0

Je fini par utiliser une UNION (prend moins d'une seconde maintenant), je l'ai fait un SELECT AgentName bruts1, Commission1, NULL, NULL, NULL, NULL FROM. UNION SELECT nomOrgent, NULL, NULL, Gross2, Commission2, NULL, NULL DE ... puis fait un choix parmi ceux-ci et groupés et additionnés –

0

Vérifiez votre bloc SELECT, il se lit comme suit:

SELECT AgentName,
SUM (sales1.Amount) AS bruts1,
SUM (sales1.Amount * sales1.Commission) AS Commission1,
SUM (sales2.Amount) AS Gross2,
SUM (sales2.Amount * sales2.Commission) AS Commission2

et vous joindrez sur une table Ventes3 dont les valeurs ne sont pas présents dans e e clause SELECT. Cela confond SQL Server. Supprimez le INNER JOIN sur Sales3 et c'est OU pièce dans le bloc WHERE et ça va fonctionner.

OU

Ajoutez ces éléments au bloc SELECT.

+0

Ce fut juste une erreur lors de l'ajout du code dans la question –

1

Je suggère fortement diviser cela en 3 requêtes indépendantes, puis fusionner les résultats via UNION

0

Ceci est juste un coup de feu dans l'obscurité w/o toute information de table (taille, schéma, index), mais essayez déplacer le filtre de date ci-dessous les opérateurs de jointure:

SELECT agentName, 
      SUM(s1.Amount) AS Gross1, 
      SUM(s1.Amount * s1.Commission) AS Commission1, 
      SUM(s2.Amount) AS Gross2, 
      SUM(s2.Amount * s2.Commission) AS Commission2 
    FROM agent 
    INNER JOIN (
     SELECT sales1.agentID, Commission, Amount 
     FROM sales1 WHERE saleId IN (
       SELECT saleId FROM saleDate 
       WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1) 
     ) s1 ON agent.agentId = s1.agentId 
    INNER JOIN (
     SELECT sales2.agentID, Commission, Amount 
     FROM sales2 WHERE saleId IN (
       SELECT saleId FROM saleDate 
       WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1) 
     ) s2 ON agent.agentId = s2.agentId; 
-- INNER JOIN (
--  SELECT sales3.agentID 
--   FROM sales3 WHERE saleId IN (
--    SELECT saleId FROM saleDate 
--    WHERE saleDate.myDate BETWEEN @minDate1 AND @maxDate1) 
--  ) s3 ON agent.agentId = s3.agentId; 
Questions connexes