2009-06-16 7 views
6

Dans ma base de données MS SQL Server, je tire des données de transaction basées sur une variété de codes différents qui sont dans une colonne.SQL CASE vs JOIN efficacité

Serait-il plus efficace:

  • rejoindre la même table encore et pour chaque code dans une clause WHERE

  • font des déclarations multiples de cas sur la table entière (ci-dessous)

  • font des déclarations multiples de cas sur toute la table, mais le limiter par une clause WHERE SubsidCde IN ('AA','BA','BB', etc)

Nous avons tellement de requêtes en cours d'exécution par seconde que même si j'ai essayé les 3 méthodes, je n'ai pas de résultats définitifs.

SELECT 
    SUM(CASE WHEN Subsid_Cde = 'AA' THEN Trans_Amt END),0) [AA], 
    SUM(CASE WHEN Subsid_Cde = 'BA' THEN Trans_Amt END),0) [BA], 
    SUM(CASE WHEN Subsid_Cde = 'BB' THEN Trans_Amt END),0) [BB] 
FROM 
    Transactions 

-- There are 8 more rows like this, using a different code for each line 
+0

Voir http://sqlblog.com/blogs/linchi_shea/archive/2011/04/04/performance-impact-the-cost-of-doing-small-lookups-in-a-large-batch.aspx –

Répondre

3

Si vous sommer tous les possibles (ou la plupart) des valeurs de champ Subsid_Cde, alors CASE est plus rapide car il ne scanne pas plusieurs fois la table comme il agrège les sommes. Si vous recherchez uniquement un petit sous-ensemble de champs Subsid_Cde possibles, les sélections/jointures séparées (avec un index sur Subsid_Cde) fonctionneront plus rapidement.

Vous devez apprendre à lire les plans d'exécution, alors vous serez capable de comprendre ces choses par vous-même.

En outre, alternativement, vous pouvez faire GROUP BY sur Subsid_Cde enveloppé dans une clause PIVOT (Google pour PIVOT MS SQL Server 2005)

1

Utilisez ceci:

SELECT (
     SELECT SUM(Trans_Amt) 
     FROM Transactions 
     WHERE Subsid_Cde = 'AA' 
     ) AS sum_aa, 
     (
     SELECT SUM(Trans_Amt) 
     FROM Transactions 
     WHERE Subsid_Cde = 'BB' 
     ) AS sum_bb 

, sans clause externe FROM ou WHERE.

En SQL Server 2005+, utilisez ceci:

SELECT [AA], [BB] 
FROM (
     SELECT trans_amt, subsid_cde 
     FROM transactions 
     ) q 
PIVOT (
     SUM(trans_amt) 
     FOR subsid_cde IN (['AA'], ['BB']) 
     ) 
2

3 est votre meilleur pari. Il est facile à lire, il est facile à modifier plus tard, et il devrait utiliser les index que vous avez définis et que vous prévoyez d'utiliser (encore, vérifiez).

--1 Parfois, vous devez vous joindre à la même table. Mais ce n'est pas l'un d'entre eux et rejoindre chaque fois que vous avez besoin d'inclure un nouveau Subsid_Cde fait pour SQL moins lisible sans vraiment gagner quoi que ce soit.

- 2 Les tables de transactions ont tendance à devenir très volumineuses, donc vous ne voulez JAMAIS analyser la totalité de la table. DonC# 2 est définitivement hors, à moins que les codes que vous utiliserez dans votre requête vous renvoie toutes les lignes de toute façon.