The Power of Cross Join

http://weblogs.sqlteam.com/jeffs/archive/2005/09/12/7755.aspx

Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Cual es la diferencia entre CROSS APPLY y CROSS JOIN

Traducido de:
http://weblogs.sqlteam.com/jeffs/archive/2007/10/18/sql-server-cross-apply.aspx
Pienso que la manera mas fácil de pensar la sentencia CROSS APPLY es que es semejante a hacer un CROSS JOIN con un sub-select correlativo en vez de una tabla derivada.

Digamos, una tabla derivada es "auto-contenida" de modo que las tablas y columnas que referencia no son accesibles por el select principal, aunque variables y parámetros pueden ser referenciados.
Por ejemplo, veamos:

select A.*, b.X
from A
cross join (select B.X from B where B.Val=A.Val) b

Esta sentencia no es válida, porque A.Val está fuera del alcance al estar dentro de la tabla derivada. Esto es porque la tabla derivada es evaluada de manera independiente de las otras tablas en el Select.
Para limitar los registros en Tabla B de manera de cumplir la condición B.Val = A.Val, nosotros tenemos que hacerlo "fuera" de la tabla derivada por medio de un join o en el criterio.

select A.*, b.X
from A
cross join (select * from B) b
where A.Val = b.Val

(por supuesto, lo de arriba es equivalente a hacer un inner join en la tabla derivada o simplemente uniendo a la tabla B).

También, tengamos en cuenta que el alcance de las tablas derivadas no rige solamente para los CROSS JOINS sino que también se aplica a todos los otros JOINS (CROSS, INNER, OUTER) e incluso para UNION. Todas estas sentencias usan tablas derivadas "auto-contenidas".

Esto es diferente a un sub-select correlativo en donde el SELECT principal está en el alcance para el sub-query. El sub-select es evaluado por cada registro en el query, de manera que otras tablas y columnas en el SELECT están disponibles.

select A.*, (select B.X from B where B.Val=A.Val) as X
from A

(obviamente el subquery tiene que regresar solo un registro).

Esta es una manera facil de pensar las diferencia entre CROSS JOIN y CROSS APPLY. CROSS JOIN, tal como vimos, une a una tabla derivada, sin embargo, CROSS APPLY, a pesar de lucir como un JOIN en realidad es aplicado al subselect correlativo. Esto impone las ventajas de subselects correlativos y además tiene implicaciones a nivel de performance.

Ahora si, podemos reescribir nuestro primer ejemplo usando CROSS APPLY y quedaría de la siguiente forma:

select A.*, b.X
from A
cross apply (select B.X from B where B.Val=A.Val) b

Como ahora aplicamos un APPLY y no un JOIN, A.Val está en alcance y esto funciona ok.

Table Valued User Defined Functions

Las mismas reglas aplican cuando usamos Table-Valued User-Defined Functions:

select A.*, B.X
from A
cross join dbo.UDF(A.Val) B

Esto es no válido nuevamente. A.Val no está en alcance para ser usado por la UDF.

Lo mejor que podíamos hacer antes de SQL 2005 era usar un subselect correlativo:

select A.*, (select X from dbo.UDF(A.Val)) X
from A

Sin embargo esto no es funcionalmente equivalente. La UDF no regresa mas de un registro o eso sería un error.

Con SQL 2005 podemos también en este caso usar CROSS APPLY y todo funcionará perfectamente:

select A.*, b.X
from A
cross apply dbo.UDF(A.Val) b

Esta es una manera de pensar las diferencias entre JOIN y APPLY, JOIN combina dos resultsets separados, pero APPLY es mas que un loop que evalua un resultset una y otra vez por cada registro.
Esto significa que en general APPLY será menos eficiente que un JOIN, del mismo modo que sub-selects correlativos son menos eficientes que tablas derivadas.

Entonces, cual es la ventaja de usar CROSS APPLY en vez de un sub-select correlacionado?
Bueno, muchas ventajas, por empezar...es mucho mas poderoso !.


CROSS APPLY puede regresar múltiples registros.

Esto nos permite hacer cosas como "joinear" una tabla a una función que parsear una columna csv en esa misma tabla en multiples registros.

select A.ID, b.Val
from A
cross apply dbo.ParseCSV(A.CSV) b

Cuando la funcion ParseCSV regresa multiples registros, simplemente actua como si hubiesemos joineado una tabla, duplicando los registros en tabla A por cada registro en la tabla de join.
Esto no se puede hacer con un sub-select correlativo, porque tira error.


CROSS APPLY puede retornar múltiples columnas.

De nuevo, en un sub-select correlativo podemos devolver un solo valor.
Si escribimos un script que regrese una sumatoria, podemos usar un subselect como el siguiente:

select o.*,
(select sum(Amount) from Order o
where p.OrderDate <= o.OrderDate) as RunningSum
from Order o

Sin embargo, que pasa si queremos regresar sumas adicionales de pedidos basados en algún otro criterio (pedidos con el mismo "ordercode")?.
Necesitaríamos otro subselect correlacionado, reduciendo la eficacia de nuestro select.

select o.*,
(select sum(Amount) from Order o
where p.OrderDate <= o.OrderDate) as RunningSum,
(select sum(Amount) from Order o
where p.OrderCode = o.OrderCode and p.OrderDate <= o.OrderDate) as SameCode
from Order o

Pero con un CROSS-APPLY seria mucho mas sencillo.

select o.*, rs.RunningSum, rs.SameCode
from Order o
cross apply
(
select
sum(Amount) as RunningSum,
sum(case when p.OrderCode = o.OrderCode then Amount else 0 end) as SameCode
from Order P
where P.OrderDate <= O.OrderDate
) rs


Entonces, tenemos el beneficio de regresar multiples columnas como si fuese una tabla derivada, y también tenemos la habilidad de referenciar valores en nuestro select.
Bastante poderoso.

Con CROSS APPLY podemos facilmente recuperar columnas del registro anterior en una tabla.

select o.*, prev.*
from Order o
cross apply
(
select top 1 *
from Order P where P.OrderDate < O.OrderDate
order by OrderDate DESC
) prev

Note que el script anterior no regresará pedidos que no tengan un pedido anterior, debemos usar OUTER APPLY para asegurarnos que todos los pedidos serán regresados, incluso si no existen pedidos previos.

select o.*, prev.*
from Order o
outer apply
(
select top 1 *
from Order P where P.OrderDate < O.OrderDate
order by OrderDate DESC
) prev


Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Como encontrar un texto dentro de todos los stored procedures en SQL Server 2005

SELECT ROUTINE_NAME, ROUTINE_DEFINITION
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%foobar%'
AND ROUTINE_TYPE='PROCEDURE'

Nos valemos de la función ROUTINE_DEFINITION que nos devuelve la definición o codificación de cualquier objeto dentro una base de datos.


Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

CXPACKET wait type en SQL Server

Problema
Tenemos un servidor con mas de un CPU y experimentamos altos valores de CXPACKET wait types. Esto ocurre por las queries que se ejecutan en paralelo y el desafío es entender como las diferentes versiones de un query pueden impactar en los valores de los CXPACKET waits. En la nota del link se analizan como cambios en un query pueden impactar en CXPACKET waits.
Solución
El objetivo del tip de la nota enlazada es incrementar la performance del query, disminuir el valor de CXPACKET waits sin reducir MAXDOP.
Veamos la nota original y los ejemplos de como recudir CXPACKET waits.

Link: http://www.mssqltips.com/tip.asp?tip=2027



Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Artículos de Kimball - Datawarehouse

Un seria ultra-interesante de artículos de Kimball, el gurú del Datawarehouse:
http://www.rkimball.com/html/articles.html
http://www.decisionone.co.uk/resources/KimballArticles.htm

Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

sp_who2 - Quien, cuando, como?

En este link podemos ver una profunda explicación sobre la historia del sp_who2, desde su origen como sp no documentado hasta el dia de hoy.
En esta profunda nota se pueden ver una clara explicación y un interesante script que se puede agregar a nuestro arsenal de tools administrativas.

http://www.sqlservercentral.com/articles/sp_who2/70222/


Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

Información acerca de los reportes scheduleados

Muchas veces tenemos una gran cantidad de reportes programados similares, pero necesitamos obtener info detallada de los mismos.

El siguiente script--->
http://www.sqlexperto.com.ar/index.php?topic=21.0 nos da la forma de obtener la lista de los reportes programados y sus jobs.



Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...

T-SQL - Gráfica de los distintos tipos de Joins

Yo pienso que esta imagen nos da la respuesta clara y exacta de como funciona cada uno de los joins disponibles en T-S
( click en la imagen para agrandarla)

















Hugo Román Bernachea
Mail de contacto: SQLServer777@gmail.com

Microsoft Certified DBA
Microsoft Certified Trainer
Twitter: @bernachea

Read More...