2012-02-08 22 views
6

Ho una query come la seguente:semplificare SQL utilizzando CTE

SELECT A.a, A.b, B.c, 
(CASE WHEN ... THEN ... ELSE ... END) AS CalculatedValue, 
B.d 
FROM dbo.TableA A INNER JOIN 
     dbo.TableB B ON (...) 
WHERE (CASE WHEN ... THEN ... ELSE ... END) BETWEEN @DayStart AND @DayEnd 
GROUP BY A.a, (CASE WHEN ... THEN ... ELSE ... END), B.c 

per evitare di ripetere più volte la stessa espressione: (CASE WHEN ... THEN ... ELSE ... END) Ho voluto definire un CTE e query quale tabella utilizzando nella select, dove e il gruppo con l'espressione CalculatedValue

purtroppo questo non funziona perché i selezionati deve includere già group by durante la creazione del CTE

v'è alcuna l'altro modo che potrei usare per non ripetere il CASE WHEN... così tante volte?

risposta

7

Usa CROSS APPLY, che può essere usato per definire i campi alias e quindi fare riferimento ad esse:

SELECT A.a, 
     A.b, 
     B.c, 
     CalculatedValue, 
     B.d 
FROM  
     dbo.TableA A 
INNER JOIN 
     dbo.TableB B 
     ON (...) 
CROSS APPLY 
     (SELECT (CASE WHEN ... THEN ... ELSE ... END)) CxA(CalculatedValue) 
WHERE CalculatedValue BETWEEN @DayStart AND @DayEnd 
GROUP BY A.a, CalculatedValue, B.c 

Il CxA è solo un alias e si può chiamarlo quello che vuoi.

+0

Grazie a JNK, questo ha risolto il problema, lo stesso tempo di esecuzione, ma in modo codice più pulito rispetto a prima, +1 e bandiera verde ;-) –

+0

Felice di aiutare! L'ho saputo solo di recente e ha reso molte cose più semplici. – JNK

+0

Diventa davvero divertente quando si incapsula la logica comune in funzioni con valori di tabella. Le domande possono finire per leggere 'table CROSS APPLY udf1 CROSS APPLY udf2 CROSS APPLY udf3' e tutto il 'normale' SQL nascosto! – MatBailie

0

Per quanto sopra, penso che potreste fare solo due strati di CTE. Il primo dovrebbe fare Calcola per tutti, il secondo dovrebbe selezionare dal primo CTE e filtrare in base al valore calcolato. La query finale entrerebbe nel secondo strato CTE.

Solo un pensiero.