2010-02-22 15 views
9

Estoy usando SqlServer 2005 y tengo una columna que he nombrado.Filtro basado en un nombre de columna con alias

La consulta es algo así como:

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

Sin embargo, esto me da el error:

"Invalid column name 'myAlias'."

¿Hay una manera de evitar esto? En el pasado, he incluido la definición de la columna en la sección WHERE o HAVING, pero esas eran en su mayoría simples, IE COUNT (*) o lo que sea. Puedo incluir toda la definición de columna en esta consulta ad-hoc, pero si por alguna razón tuviera que hacer esto en una consulta de producción, preferiría tener la definición de columna solo una vez, así que no tengo que actualizar ambas (y olvide hacer uno en algún momento)

Respuesta

11

No se puede hacer referencia a los alias en una cláusula where así ... que o bien tienen que duplicar el caso en los DONDE, o puede utilizar una subconsulta como esto:

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

Por desgracia, esperaba que fuera más simple. –

+0

Yo también, debería haber una solución más genérica en realidad –

1

ponga la caja en el lugar. SQL Server será lo suficientemente inteligente como para evaluar simplemente que una vez lo que no están realmente duplicando el código:

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

que podría envolverlo en una tabla derivada:

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 

Sin embargo, trato de evite tener tablas derivadas sin un DONDE restrictivo. Puede intentarlo para ver si afecta el rendimiento o no.

+0

@KM, mi preocupación era más sobre mí actualizando un CASO y olvidando actualizar el segundo. Al igual que usted, espero que SQL Server optimice la segunda llamada –

1

poner la misma CASE declaración en la cláusula 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 

EDITAR

Otra opción es nido de la consulta:

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

(Editar: eliminado HAVING opción, ya que esto era incorrecto (gracias @OMG Ponies))

+0

Tiene toda la razón: borraré esa parte. – Codesleuth

+0

@OMG ponys: pruébalo en SQL Server. sin grupo por, es lo mismo que DONDE más o menos ... http://msdn.microsoft.com/en-us/library/ms180199%28SQL.90%29.aspx Así que la solución de Codesleuth puede haber sido correcta sin el uso de derivados tabla – gbn

+0

@gbn: ¡raro! Definitivamente intentaré cuando llegue a trabajar. Perdón por eso, Codesleuth. –

5

Uso de CTE es también una opción:

;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

Gracias Philip, no estoy familiarizado con CTE, parece que es una vista temporal. ¿Sería eso una declaración justa? –

+0

@nathan koop: sí, al igual que las soluciones de tabla derivadas ofrecidas también ... – gbn

+0

Gracias lo echaré un vistazo –

0

Terminé creando una tabla temporal para hacer esto. Aquí hay un pseudo código para darle una idea. Esto funcionó con una unión compleja, solo estoy mostrando un caso simple aquí.

--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 
Cuestiones relacionadas