2010-02-22 10 views
9

Sto usando SqlServer 2005 e ho una colonna che ho chiamato.Filtro basato su un nome di colonna con alias

La query è qualcosa di simile:

SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias 
FROM myTable 
WHERE myAlias IS NOT NULL 

Tuttavia, questo mi dà l'errore:

"Invalid column name 'myAlias'."

C'è un modo per aggirare questo? In passato ho incluso la definizione della colonna nella sezione WHERE o HAVING, ma quelli erano per lo più semplici, IE COUNT (*) o qualsiasi altra cosa. Posso includere l'intera definizione di colonna in questa query ad-hoc, ma se per qualche ragione dovessi farlo in una query di produzione preferirei avere la definizione della colonna solo una volta, quindi non devo aggiornare entrambi (e dimentica di farlo a un certo punto)

risposta

11

Non è possibile fare riferimento alias in una clausola WHERE come quello ... hai i duplicare il CASE in WHERE, oppure è possibile utilizzare una sottoquery come questo:

SELECT id, myAlias 
FROM 
(
    SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias 
    FROM myTable 
) data 
WHERE myAlias IS NOT NULL 
+2

Ahimè, speravo che sarebbe stato più semplice. –

+0

Anch'io, dovrebbe esserci una soluzione più generica in realtà –

1

mettere il caso nel dove. SQL Server sarà abbastanza intelligente per valutare solo una sola volta in modo da non siete veramente duplicare il codice:

SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias 
FROM myTable 
WHERE CASE WHEN <snip extensive column definition> END IS NOT NULL 

si poteva avvolgerlo in una tabella derivata:

SELECT dt.id, dt.myAlias 
    FROM (
      SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias 
      FROM myTable 
     ) dt 
    WHERE dt.myAlias IS NOT NULL 

Tuttavia, cerco di evitare di avere tabelle derivate senza un WHERE restrittivo. Puoi provarlo per vedere se influisce o meno sulle prestazioni.

+0

@ KM, la mia preoccupazione era più su di me l'aggiornamento di un CASO e dimenticando di aggiornare il secondo. Come te, mi aspetto che SQL Server ottimizzerà la seconda chiamata –

1

mettere lo stesso CASE dichiarazione nella clausola WHERE:

SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias 
FROM myTable 
WHERE CASE WHEN <snip extensive column definition> END IS NOT NULL 

EDIT

Un'altra opzione è quella di nido query:

SELECT id, myAlias 
FROM (
    SELECT id, CASE WHEN <snip extensive column definition> END AS myAlias 
    FROM myTable 
) AS subTable 
WHERE myAlias IS NOT NULL 

(Edit: rimosso HAVING opzione, perché non era corretto (grazie @OMG Ponies))

+0

Hai ragione - eliminerò quella parte. – Codesleuth

+0

ponies @OMG: provalo in SQL Server. senza gruppo da, è lo stesso WHERE praticamente ... http://msdn.microsoft.com/en-us/library/ms180199%28SQL.90%29.aspx Quindi la soluzione di Codesleuth potrebbe essere stata corretta senza l'uso di derivato tabella – gbn

+0

@gbn: strano! Ci proveremo sicuramente quando arriverò al lavoro. Mi dispiace, Codesleuth. –

5

Utilizzando CTE è anche un'opzione:

;with cte (id, myAlias) 
as (select id, case when <snip extensive column definition> end as myAlias 
     from myTable) 
select id, myAlias 
    from cte 
    where myAlias is not null 
+0

Grazie Philip, non ho familiarità con CTE, sembra che sia una visualizzazione temporanea. Sarebbe una dichiarazione giusta? –

+0

@nathan koop: sì, come le soluzioni da tavolo derivate offerte anche ... – gbn

+0

Grazie Diamo un'occhiata in esso –

0

Ho finito per creare un tavolo temporaneo per fare questo. Ecco qualche pseudo codice per darti un'idea. Questo ha funzionato con un join complesso, sto solo mostrando un caso semplice qui.

--Check to see if the temp table already exists 
If(OBJECT_ID('tempdb..#TempTable') Is Not Null) 
Begin 
    DROP TABLE #TempTable 
End 

--Create the temp table 
CREATE TABLE #TempTable 
{ 
    YourValues NVARCHAR(100) 
} 

--Insert your data into the temp table   
INSERT INTO #TempTable(YourValues) 
SELECT yt.Column1 as YourColumnOne FROM YourTable yt 

--Query the filtered data based on the aliased column  
SELECT * 
FROM #TempTable 
WHERE YourColumnOne = 'DataToFilterOn' 

--Don't forget to remove the temp table 
DROP TABLE #TempTable