2010-03-16 12 views
6

¿Es esta válida SQL ANSI ?:Reutilización anticipada (o reordenada) de columnas derivadas en una consulta: ¿es válido ANSI SQL?

SELECT 1 AS X 
     ,2 * X AS Y 
     ,3 * Y AS Z 

Debido a Teradata (12) puede hacer esto, así como el presente (sí, loco no lo es):

SELECT 3 * Y AS Z 
     ,2 * X AS Y 
     ,1 AS X 

Pero SQL Server 2005 requiere algo como esto:

SELECT X 
     ,Y 
     ,3 * Y AS Z 
FROM (
     SELECT X 
       ,2 * X AS Y 
     FROM (
       SELECT 1 AS X 
       ) AS X 
     ) AS Y 
+0

Me pregunto qué error arroja si prueba 'SELECT 2 * y AS x, 2 * x AS y' –

Respuesta

5

No, no es válido ANSI. ANSI supone que todos los elementos de la cláusula SELECT se evalúan a la vez.

Y I'd've escrito en SQL 2005 como:

SELECT * 
FROM  (SELECT 1 AS X) X 
CROSS APPLY (SELECT 2 * X AS Y) Y 
CROSS APPLY (SELECT 3 * Y AS Z) Z 
; 
+1

Una alternativa inteligente a los CTE - Lo tendré en cuenta. Desafortunadamente, Teradata no admite CTE apilados (creo que podría ser compatible con uno, por lo que está en mi lista para investigar) ni el operador APPLY. –

+0

Por supuesto, la reutilización de alias en Teradata no es ANSI SQL, pero CROSS APPLY también es una extensión de SQL estándar :-) – dnoeth

2

No tiene por qué ser fea en SQL Server 2005 +. Es por eso que Microsoft introdujo CTE:

WITH T1 AS (SELECT 1 AS X), 
    T2 AS (SELECT X, 2 * X AS Y FROM T1) 
SELECT X, Y, 3 * Y AS Z FROM T2 

O usted podría utilizar CROSS APPLY como demuestra Rob - que puede o no puede trabajar para usted en función de las características específicas de la consulta.

Admito que no es tan limpio como el de Teradata, pero no es tan malo como la versión de la subconsulta, y el ejemplo original de Teradata en su pregunta definitivamente no forma parte del estándar SQL-92.

También me gustaría añadir que en su original ejemplo, los X, Y y Z columnas no son, técnicamente, columnas derivadas como usted los llama. Al menos en lo que respecta a Microsoft y ANSI, son solo alias, y un alias no puede hacer referencia a otro alias hasta que realmente se convierta en una columna (es decir, a través de una subconsulta o CTE).

+0

Normalmente utilizamos múltiples CTE apilados en SQL Server. Desafortunadamente, no están permitidos en Teradata ;-(Estoy tratando de encontrar un término medio. Lo que estoy descubriendo es que Teradata se comporta MUCHO mejor cuando no anida, y usa este truco, pero me preocupa que puede que no continúe funcionando y hubiera sido mejor dejar mis CTE convertidos en anidamiento si esto se rompe en Teradata en el futuro. –

Cuestiones relacionadas