2009-06-16 14 views
6

Nel mio database MS SQL Server sto prelevando i dati delle transazioni in base a una varietà di codici diversi che si trovano in una colonna.SQL CASE rispetto all'efficienza JOIN

sarebbe più efficiente:

  • unirsi allo stesso tavolo più e più volte per ogni codice in una clausola WHERE

  • do più istruzioni caso sulla intera tabella (vedi sotto)

  • do più istruzioni case su tutto il tavolo, ma limitarla da una clausola WHERE SubsidCde IN ('AA','BA','BB', etc)

Abbiamo così tante query al secondo che anche se ho provato tutti e 3 i metodi non ottengo risultati definitivi.

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

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

risposta

3

Se stai sommando tutti i possibili (o la maggior parte) i valori di campo Subsid_Cde, allora CASE è più veloce in quanto non eseguirà la scansione del tavolo più volte come si aggrega le somme. Se stai cercando solo un piccolo sottoinsieme di possibili campi Subsid_Cde, separa selects/joins (insieme a un indice su Subsid_Cde) funzionerà più velocemente.

Hai bisogno di imparare a leggere i piani di esecuzione, quindi sarai in grado di capire queste cose da solo.

Inoltre, in alternativa, si potrebbe fare un GROUP BY sul Subsid_Cde avvolto in una clausola PIVOT (google per PIVOT MS SQL Server 2005)

1

Utilizzare questa:

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 

, senza esterni FROM o WHERE clausola.

In SQL Server 2005+, utilizzare questo:

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

3 è la soluzione migliore. È facile da leggere, è facile da modificare in seguito e dovrebbe utilizzare gli indici che hai definito e che si prevede utilizzino (ancora, controlla).

--1 A volte è necessario unirsi alla stessa tabella. Ma questo non è uno di questi e unirsi ogni volta che è necessario includere un nuovo Subsid_Cde rende SQL meno leggibile senza veramente guadagnare nulla.

--2 Le tabelle di transazioni tendono a diventare molto grandi, quindi NON si desidera eseguire la scansione dell'intero tavolo. Quindi # 2 è decisamente fuori, a meno che i codici che userete nella vostra query vi restituiscano comunque tutte le righe.