<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://geeks.ms/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang=""><title type="html">Freddy Angarita</title><subtitle type="html">Tecnologías Microsoft, especialmente SqlServer 2008 y Desarrollo .Net</subtitle><id>http://geeks.ms/blogs/fangarita/atom.aspx</id><link rel="alternate" type="text/html" href="http://geeks.ms/blogs/fangarita/default.aspx" /><link rel="self" type="application/atom+xml" href="http://geeks.ms/blogs/fangarita/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.31106.3070">Community Server</generator><updated>2010-10-28T16:36:00Z</updated><entry><title>[PPT] Presentación Novedades SqlServer 2012 BI</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2012/04/25/pdf-presentaci-243-n-novedades-sqlserver-2012-bi.aspx" /><link rel="enclosure" type="application/vnd.openxmlformats-officedocument.pres" length="1340337" href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.20.46.65/SQL-Saturday.pptx" /><id>/blogs/fangarita/archive/2012/04/25/pdf-presentaci-243-n-novedades-sqlserver-2012-bi.aspx</id><published>2012-04-25T20:21:00Z</published><updated>2012-04-25T20:21:00Z</updated><content type="html">&lt;p&gt;Adjunto el archivo de la presentaci&amp;oacute;n sobre novedades de Inteligencia de negocios en el Sql Server 2012 - Del evento&amp;nbsp;Saturday 124&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=204665" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[WebCast] Creación de un Modelo Semántico Tabular Sql Server 2012</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2012/04/10/webcast-creaci-243-n-de-un-modelo-sem-225-ntico-tabular-sql-server-2012.aspx" /><id>/blogs/fangarita/archive/2012/04/10/webcast-creaci-243-n-de-un-modelo-sem-225-ntico-tabular-sql-server-2012.aspx</id><published>2012-04-10T16:32:00Z</published><updated>2012-04-10T16:32:00Z</updated><content type="html">&lt;p&gt;En el video se observa paso a paso la creaci&amp;oacute;n&amp;nbsp;y exploraci&amp;oacute;n de un modelo sem&amp;aacute;ntico tabular en Sql Server 2012&lt;/p&gt;
&lt;p align="center"&gt;&lt;iframe width="400" frameborder="0" src="http://player.vimeo.com/video/40091958?title=0&amp;amp;byline=0&amp;amp;portrait=0" height="300"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=204384" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Nueva versión crear tabla a partir de un texto separado por comas (CSV)</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2012/01/17/code-nueva-versi-243-n-crear-tabla-a-partir-de-un-texto-separado-por-comas-csv.aspx" /><id>/blogs/fangarita/archive/2012/01/17/code-nueva-versi-243-n-crear-tabla-a-partir-de-un-texto-separado-por-comas-csv.aspx</id><published>2012-01-18T02:16:00Z</published><updated>2012-01-18T02:16:00Z</updated><content type="html">&lt;p&gt;&lt;span&gt;En un art&amp;iacute;culo anterior, &lt;/span&gt;&lt;span&gt;&lt;a href="http://geeks.ms/blogs/fangarita/archive/2011/01/03/code-crear-una-tabla-a-apartir-de-un-texto-se.aspx"&gt;&lt;span style="color:#000000;"&gt;[Code] Crear una tabla a partir de un texto separado por comas (CSV)&lt;/span&gt;&lt;/a&gt;, se present&amp;oacute; c&amp;oacute;mo realizar &amp;eacute;sta tarea de la manera m&amp;aacute;s simple, ahora, se complementar&amp;aacute; &amp;eacute;sta soluci&amp;oacute;n presentando una alternativa que usa CTEs para realizar el trabajo recursivo de analizar las palabras en la sentencia&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Usando la capacida de las expresiones CTEs de crear iteraciones se permite la creaci&amp;oacute;n de la iteraci&amp;oacute;n consigo mismo, es decir en la primera parte, se pone la semilla y en la segunda parte (luego de union all) se implementa la iteraci&amp;oacute;n, la cual devuelve las posiciones inicial y final del texto al que se le va a aplicar substring:&lt;/p&gt;
&lt;pre&gt;CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(512)) 
RETURNS table 
AS 
RETURN ( 
    WITH Pieces(pn, start, stop) AS ( 
      SELECT 1, 1, CHARINDEX(@sep, @s) 
      UNION ALL 
      SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1) 
      FROM Pieces 
      WHERE stop &amp;gt; 0 
    ) 
    SELECT pn, 
      SUBSTRING(@s, start, CASE WHEN stop &amp;gt; 0 THEN stop-start ELSE 512 END) AS s 
    FROM Pieces 
  ) 
&lt;/pre&gt;
&lt;p&gt;La soluci&amp;oacute;n anterior presenta una forma interesante de aproximarse al problema pero a&amp;uacute;n usa recursi&amp;oacute;n, esto se puede eliminar usando XML como base de an&amp;aacute;lisis&lt;/p&gt;
&lt;pre&gt;CREATE FUNCTION [dbo].[Split] (@sep VARCHAR(32), @s VARCHAR(MAX)) 
 
RETURNS @t TABLE 
    ( 
        val VARCHAR(MAX) 
    )    
AS 
    BEGIN 
        DECLARE @xml XML 
        SET @XML = N&amp;#39;&amp;#39; + REPLACE(@s, @sep, &amp;#39;&amp;#39;) + &amp;#39;&amp;#39; 
 
        INSERT INTO @t(val) 
        SELECT r.value(&amp;#39;.&amp;#39;,&amp;#39;VARCHAR(255)&amp;#39;) as Item 
        FROM @xml.nodes(&amp;#39;//root/r&amp;#39;) AS RECORDS(r) 
 
        RETURN 
    END 
&lt;/pre&gt;
&lt;p&gt;El truco consiste en convertir el texto, en un xml y luego usando el tipo de datos especial (y sus funciones) leemos la informaci&amp;oacute;n como una tabla desde XML, el problema con esta soluci&amp;oacute;n es que tiene problemas de desempe&amp;ntilde;o y se presenta solo como referencia&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n se presenta uno de&amp;nbsp;mis trucos favoritos el uso de la funci&amp;oacute;n &lt;a href="http://msdn.microsoft.com/es-co/library/cc280463.aspx"&gt;dm_fts_parser&lt;/a&gt;, la cual permite realizar &amp;eacute;ste an&amp;aacute;lisis r&amp;aacute;pidamente, con la ventaja de:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ser una funci&amp;oacute;n del sistema, &lt;/li&gt;
&lt;li&gt;permitir configurar el idioma&lt;/li&gt;
&lt;li&gt;Ser sensible al acentro y may&amp;uacute;sculas&lt;/li&gt;
&lt;li&gt;Poder usar una lista de palabras a ignorar&lt;/li&gt;
&lt;li&gt;M&amp;aacute;s funcionalidades&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;select display_term from sys.dm_fts_parser(&amp;#39;&amp;quot;&amp;#39; + &amp;#39;Mi texto separado por espacios&amp;#39; + &amp;#39;&amp;quot;&amp;#39;, 1033, 0,0) &lt;/pre&gt;
&lt;p&gt;Es ejemplo est&amp;aacute; para idioma ingl&amp;eacute;s con el c&amp;oacute;digo 1033, para un listado completo&amp;nbsp;se puede consultar el listado &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.splocale.lcid.aspx"&gt;LCID&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda, &lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=202789" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Cómo convertir un número a letras</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2012/01/17/code-c-243-mo-convertir-un-n-250-mero-a-letras.aspx" /><id>/blogs/fangarita/archive/2012/01/17/code-c-243-mo-convertir-un-n-250-mero-a-letras.aspx</id><published>2012-01-18T02:02:00Z</published><updated>2012-01-18T02:02:00Z</updated><content type="html">&lt;p&gt;Lo primero que se debe advertir antes de poner el c&amp;oacute;digo a disposici&amp;oacute;n de todos, es que no recomiendo esta aproximaci&amp;oacute;n de manera pr&amp;aacute;ctica dado que SQL est&amp;aacute; optimizado para c&amp;aacute;lculos basados en conjuntos (Selects, Joins y dem&amp;aacute;s); manejo de cadenas y c&amp;aacute;lculos se deber&amp;iacute;an hacer de otras maneras (CLR, C&amp;oacute;digo Ciente, etc.), pero si alguna vez se necesita o si se quiere traducir a otro lenguaje se puede usar el siguiente c&amp;oacute;digo para generar n&amp;uacute;meros como letras. Para tener m&amp;aacute;s claridad sobre el tema de buenas pr&amp;aacute;cticas se puede revisar el art&amp;iacute;culo de &lt;a href="http://geeks.ms/blogs/fangarita/archive/2011/01/17/info-optimizaci-243-n-de-consultas-parte-1-generalidades.aspx"&gt;optimizaci&amp;oacute;n de consultas&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;No es el c&amp;oacute;digo m&amp;aacute;s eficiente que se puede escribir para el tema, pero funciona:&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;create PROCEDURE [dbo].[sp_Dinero_a_Texto]
(
  @Numero NUMERIC(19,4)
 )
AS
BEGIN
 
  SET NOCOUNT ON
  DECLARE @lnEntero INT,
    @lcRetorno VARCHAR(512),
    @lnTerna INT,
    @lcMiles VARCHAR(512),
    @lcCadena VARCHAR(512),
    @lnUnidades INT,
    @lnDecenas INT,
    @lnCentenas INT,
    @lnFraccion INT
 
  SELECT @lnEntero = CAST(@Numero AS INT),
    @lnFraccion = (@Numero - @lnEntero) * 100,
    @lcRetorno = &amp;#39;&amp;#39;,
    @lnTerna = 1
 
  WHILE @lnEntero &amp;gt; 0
  BEGIN /* WHILE */
 
    -- Recorro columna por columna
    SELECT @lcCadena = &amp;#39;&amp;#39;
    SELECT @lnUnidades = @lnEntero % 10
    SELECT @lnEntero = CAST(@lnEntero/10 AS INT)
    SELECT @lnDecenas = @lnEntero % 10
    SELECT @lnEntero = CAST(@lnEntero/10 AS INT)
    SELECT @lnCentenas = @lnEntero % 10
    SELECT @lnEntero = CAST(@lnEntero/10 AS INT)	

	--print cast(@lnCentenas as varchar(3)) + cast(@lnDecenas as varchar(3))+ cast(@lnUnidades as varchar(3))
	--print @lnEntero
 
    -- Analizo las unidades
    SELECT @lcCadena =
    CASE /* UNIDADES */
      WHEN @lnUnidades = 1 AND @lnTerna = 1 THEN &amp;#39;UNO &amp;#39; + @lcCadena
      WHEN @lnUnidades = 1 AND @lnTerna &amp;lt;&amp;gt; 1 THEN &amp;#39;UN &amp;#39; + @lcCadena
      WHEN @lnUnidades = 2 THEN &amp;#39;DOS &amp;#39; + @lcCadena
      WHEN @lnUnidades = 3 THEN &amp;#39;TRES &amp;#39; + @lcCadena
      WHEN @lnUnidades = 4 THEN &amp;#39;CUATRO &amp;#39; + @lcCadena
      WHEN @lnUnidades = 5 THEN &amp;#39;CINCO &amp;#39; + @lcCadena
      WHEN @lnUnidades = 6 THEN &amp;#39;SEIS &amp;#39; + @lcCadena
      WHEN @lnUnidades = 7 THEN &amp;#39;SIETE &amp;#39; + @lcCadena
      WHEN @lnUnidades = 8 THEN &amp;#39;OCHO &amp;#39; + @lcCadena
      WHEN @lnUnidades = 9 THEN &amp;#39;NUEVE &amp;#39; + @lcCadena
      ELSE @lcCadena
    END /* UNIDADES */

	print @lcCadena
 
    -- Analizo las decenas
    SELECT @lcCadena =
    CASE /* DECENAS */
      WHEN @lnDecenas = 1 THEN
        CASE @lnUnidades
          WHEN 0 THEN &amp;#39;DIEZ &amp;#39;
          WHEN 1 THEN &amp;#39;ONCE &amp;#39;
          WHEN 2 THEN &amp;#39;DOCE &amp;#39;
          WHEN 3 THEN &amp;#39;TRECE &amp;#39;
          WHEN 4 THEN &amp;#39;CATORCE &amp;#39;
          WHEN 5 THEN &amp;#39;QUINCE &amp;#39;
          ELSE &amp;#39;DIECI&amp;#39; + @lcCadena
        END
      WHEN @lnDecenas = 2 AND @lnUnidades = 0 THEN &amp;#39;VEINTE &amp;#39; + @lcCadena
      WHEN @lnDecenas = 2 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;VEINTI&amp;#39; + @lcCadena
      WHEN @lnDecenas = 3 AND @lnUnidades = 0 THEN &amp;#39;TREINTA &amp;#39; + @lcCadena
      WHEN @lnDecenas = 3 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;TREINTA Y &amp;#39; + @lcCadena
      WHEN @lnDecenas = 4 AND @lnUnidades = 0 THEN &amp;#39;CUARENTA &amp;#39; + @lcCadena
      WHEN @lnDecenas = 4 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;CUARENTA Y &amp;#39; + @lcCadena
      WHEN @lnDecenas = 5 AND @lnUnidades = 0 THEN &amp;#39;CINCUENTA &amp;#39; + @lcCadena
      WHEN @lnDecenas = 5 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;CINCUENTA Y &amp;#39; + @lcCadena
      WHEN @lnDecenas = 6 AND @lnUnidades = 0 THEN &amp;#39;SESENTA &amp;#39; + @lcCadena
      WHEN @lnDecenas = 6 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;SESENTA Y &amp;#39; + @lcCadena
      WHEN @lnDecenas = 7 AND @lnUnidades = 0 THEN &amp;#39;SETENTA &amp;#39; + @lcCadena
      WHEN @lnDecenas = 7 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;SETENTA Y &amp;#39; + @lcCadena
      WHEN @lnDecenas = 8 AND @lnUnidades = 0 THEN &amp;#39;OCHENTA &amp;#39; + @lcCadena
      WHEN @lnDecenas = 8 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;OCHENTA Y &amp;#39; + @lcCadena
      WHEN @lnDecenas = 9 AND @lnUnidades = 0 THEN &amp;#39;NOVENTA &amp;#39; + @lcCadena
      WHEN @lnDecenas = 9 AND @lnUnidades &amp;lt;&amp;gt; 0 THEN &amp;#39;NOVENTA Y &amp;#39; + @lcCadena
      ELSE @lcCadena
    END /* DECENAS */

	print @lcCadena
 
    -- Analizo las centenas
    SELECT @lcCadena =
    CASE /* CENTENAS */
      WHEN @lnCentenas = 1 AND @lnUnidades = 0 AND @lnDecenas = 0 THEN &amp;#39;CIEN &amp;#39; + @lcCadena
      WHEN @lnCentenas = 1 AND NOT(@lnUnidades = 0 AND @lnDecenas = 0) THEN &amp;#39;CIENTO &amp;#39; + @lcCadena
      WHEN @lnCentenas = 2 THEN &amp;#39;DOSCIENTOS &amp;#39; + @lcCadena
      WHEN @lnCentenas = 3 THEN &amp;#39;TRESCIENTOS &amp;#39; + @lcCadena
      WHEN @lnCentenas = 4 THEN &amp;#39;CUATROCIENTOS &amp;#39; + @lcCadena
      WHEN @lnCentenas = 5 THEN &amp;#39;QUINIENTOS &amp;#39; + @lcCadena
      WHEN @lnCentenas = 6 THEN &amp;#39;SEISCIENTOS &amp;#39; + @lcCadena
      WHEN @lnCentenas = 7 THEN &amp;#39;SETECIENTOS &amp;#39; + @lcCadena
      WHEN @lnCentenas = 8 THEN &amp;#39;OCHOCIENTOS &amp;#39; + @lcCadena
      WHEN @lnCentenas = 9 THEN &amp;#39;NOVECIENTOS &amp;#39; + @lcCadena
      ELSE @lcCadena
    END /* CENTENAS */
	print @lcCadena
 
    -- Analizo los millares
    SELECT @lcCadena =
    CASE /* TERNA */
      WHEN @lnTerna = 1 THEN @lcCadena
      WHEN @lnTerna = 2 AND (@lnUnidades + @lnDecenas + @lnCentenas &amp;lt;&amp;gt; 0) THEN @lcCadena + &amp;#39; MIL &amp;#39;
      WHEN @lnTerna = 3 AND (@lnUnidades + @lnDecenas + @lnCentenas &amp;lt;&amp;gt; 0) AND
        @lnUnidades = 1 AND @lnDecenas = 0 AND @lnCentenas = 0 THEN @lcCadena + &amp;#39; MILLON &amp;#39;
      WHEN @lnTerna = 3 AND (@lnUnidades + @lnDecenas + @lnCentenas &amp;lt;&amp;gt; 0) AND
        NOT (@lnUnidades = 1 AND @lnDecenas = 0 AND @lnCentenas = 0) THEN @lcCadena + &amp;#39; MILLONES &amp;#39;
      WHEN @lnTerna = 4 AND (@lnUnidades + @lnDecenas + @lnCentenas &amp;lt;&amp;gt; 0) THEN @lcCadena + &amp;#39; MIL MILLONES &amp;#39;
      ELSE &amp;#39;&amp;#39;
    END /* MILLARES */
	print @lcCadena
 
    -- Armo el retorno columna a columna
	--print @lcCadena
    SELECT @lcRetorno = @lcCadena + @lcRetorno
    SELECT @lnTerna = @lnTerna + 1
 
  END /* WHILE */
 
  IF @lnTerna = 1
    SELECT @lcRetorno = &amp;#39;CERO&amp;#39;
 
  SELECT RTRIM(@lcRetorno) + CASE WHEN LEN(LTRIM(STR(@lnFraccion,2))) = 1 THEN &amp;#39;0&amp;#39;+LTRIM(STR(@lnFraccion,2))
                                               ELSE LTRIM(STR(@lnFraccion,2)) END AS Texto
 
END

&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Los comentarios son bienvenidos, espero sea de ayuda, &lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=202787" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Llenado de Espacio en Datos (Generación de Datos Acumulados) por Grupos</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2012/01/08/code-llenado-de-espacio-en-datos-generaci-243-n-de-datos-acumulados-por-grupos.aspx" /><link rel="enclosure" type="application/octet-stream" length="2113" href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.20.26.48/Articulo-Acumulado-Llenando-Gaps.sql" /><id>/blogs/fangarita/archive/2012/01/08/code-llenado-de-espacio-en-datos-generaci-243-n-de-datos-acumulados-por-grupos.aspx</id><published>2012-01-08T16:34:00Z</published><updated>2012-01-08T16:34:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;Llenado de Espacio en Datos (Generaci&amp;oacute;n de Datos Acumulados) por Grupos&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Normalmente los productos de software llevan un registro de los &lt;i&gt;hechos&lt;/i&gt; que se Fsentan en el negocio, ventas, desembolsos, cobros, intereses, etc. Pero por supuesto no todos los d&amp;iacute;as se vende, se desembolsa, se cobra initereses, c&amp;oacute;mo podemos resolver de una &lt;i&gt;eficiente&lt;/i&gt; la necesidad ver los datos acumulados, este escenario, por lo meno de manera parcial, fu&amp;eacute; resuelto en un art&amp;iacute;culo anterior &lt;a href="http://geeks.ms/blogs/fangarita/archive/2010/10/28/code-c-243-mo-calcular-un-total-acumulado-r-225-pido-sin-cursores.aspx"&gt;[Code] C&amp;oacute;mo calcular un total acumulado R&amp;aacute;pido SIN Cursores&lt;/a&gt;. Este art&amp;iacute;culo complementa esa soluci&amp;oacute;n presentando c&amp;oacute;mo se har&amp;iacute;a lo mismo para generar datos acumulados (o llenar espacios) teniendo en cuenta diferentes grupos dentro de los datos&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n se presentar&amp;aacute; una aplicaci&amp;oacute;n de otro art&amp;iacute;culo llamado &lt;a href="http://geeks.ms/blogs/fangarita/archive/2010/12/22/code-c-243-mo-generar-n-filas-r-225-pido-sql-server.aspx"&gt;[Code] C&amp;oacute;mo generar N Filas R&amp;aacute;pido Sql Server&lt;/a&gt; el cual se usar&amp;aacute; para generar los datos necesarios para llenar los espacios de la informaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Datos de ejemplo&lt;/p&gt;
&lt;pre&gt;declare @hechos table (id int, fecha date, producto int, venta decimal)

insert into @hechos	values (1, &amp;#39;2011-09-01&amp;#39;, 1, 10)
insert into @hechos	values (2, &amp;#39;2011-09-03&amp;#39;, 1, 20)
insert into @hechos	values (3, &amp;#39;2011-09-04&amp;#39;, 1, 2)
insert into @hechos	values (4, &amp;#39;2011-09-08&amp;#39;, 1, 1)
insert into @hechos	values (5, &amp;#39;2011-09-10&amp;#39;, 1, 3)
insert into @hechos	values (6, &amp;#39;2011-09-12&amp;#39;, 1, 4)

insert into @hechos	values (7, &amp;#39;2011-09-01&amp;#39;, 2, 3)
insert into @hechos	values (8, &amp;#39;2011-09-03&amp;#39;, 2, 2)
insert into @hechos	values (9, &amp;#39;2011-09-04&amp;#39;, 2, 1)
insert into @hechos	values (10, &amp;#39;2011-09-08&amp;#39;, 2, 5)
insert into @hechos	values (11, &amp;#39;2011-09-10&amp;#39;, 2, 6)
insert into @hechos	values (12, &amp;#39;2011-09-12&amp;#39;, 2, 7)&lt;/pre&gt;
&lt;p&gt;Los datos en formato tabla:&lt;/p&gt;
&lt;table align="center" width="50%" cellpadding="0" cellspacing="0" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;Id&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;Fecha&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;Producto&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;Venta&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2011-09-01&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2011-09-03&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2011-09-04&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;2011-09-08&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;2011-09-10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;2011-09-12&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;2011-09-01&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;2011-09-03&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;2011-09-04&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;2011-09-08&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;2011-09-10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;2011-09-12&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Observemos que las fechas de venta para cada producto no suceden en d&amp;iacute;as consecutivos, se tienen 2 diferentes productos a los que se quiere calcularle sus ventas acumuladas por d&amp;iacute;a y una cantidad de ventas&lt;/p&gt;
&lt;p&gt;Lo primero que haremos es calcular el n&amp;uacute;mero de d&amp;iacute;as de diferencia entre la mayor y menos fecha de toda la tabla (para todos los productos)&lt;/p&gt;
&lt;pre&gt;declare @FechaMin date, @FechaMax Date, @Diferencia int
select  @FechaMin = min(Fecha), @FechaMax = MAX(Fecha) from @hechos

set @Diferencia = DATEDIFF(dd,@FechaMin, @FechaMax)&lt;/pre&gt;
&lt;p&gt;Alternativamente podr&amp;iacute;amos crear una tabla que tenga la fecha m&amp;iacute;nima y m&amp;aacute;xima por cada producto, pero se presentar&amp;aacute; as&amp;iacute; para mantener simple el ejemplo.&lt;/p&gt;
&lt;p&gt;Pasos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Se generea un CTE con una tabla que tiene todas las fechas posibles (incluso las que no est&amp;aacute;n en la tabla @hechos), llamado Fechas, El c&amp;oacute;digo de GenTable se encuentra en &lt;a href="http://geeks.ms/blogs/fangarita/archive/2010/12/22/code-c-243-mo-generar-n-filas-r-225-pido-sql-server.aspx"&gt;[Code] C&amp;oacute;mo generar N Filas R&amp;aacute;pido Sql Server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Tambi&amp;eacute;n se declara una tabla @Acumulado que tendr&amp;aacute; el resultado final con los valores acumulados por producto&lt;/li&gt;
&lt;li&gt;En el CTE ProductoFecha aplicamos una funci&amp;oacute;n de conjunto cross join para aplicar cada fecha generada a cada una de los productos de @hechos, lo que nos d&amp;aacute; como resultado todas las fechas posibles para cada producto&lt;/li&gt;
&lt;li&gt;Luego, se inserta en @Acumulado el resutaldo de hacer left join entre ProductoFecha (que tiene todas las fechas) y @Hechos lo que nos da, cada producto y cada fecha posible, en las fechas que no se realizaron ventas se agrega cero (0)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;declare @Acumulado table (fecha date, producto int, venta decimal, VentaAcumulada decimal)

;With Fechas (Fecha) as
(
select DATEADD(dd,GT.i,@FechaMin) Fecha from dbo.GenTable(0,@Diferencia,1) GT
)
, ProductoFecha (Producto, Fecha) as (
select distinct Producto, Fechas.Fecha from @hechos cross join Fechas
)
insert into @Acumulado (fecha, producto, venta, VentaAcumulada)
Select PF.Fecha, PF.Producto, isnull(H.Venta,0) as Ventas, 0  from ProductoFecha PF left join @hechos H ON PF.Producto = H.producto and PF.Fecha = h.fecha
&lt;/pre&gt;
&lt;p&gt;Ahora se procede a calcular el total acumulado por grupos:&lt;/p&gt;
&lt;pre&gt;declare @runningtotal decimal , @ProductoActual int

set @runningtotal = 0 
select @ProductoActual = 0 

--Anterior
update @Acumulado 
set 
@runningtotal = VentaAcumulada = case when not @ProductoActual = Producto then venta else 
case when Venta = 0 then @runningtotal else venta end
end
,@ProductoActual = Producto&lt;/pre&gt;
&lt;p&gt;La parte clave es donde se define el Producto actual por que permite la detecci&amp;oacute;n de cambio de grupos para generar as&amp;iacute; su acumulado, esta t&amp;eacute;cnica puede ser aplicada a m&amp;uacute;ltiples grupos, por ejemplo, ciudad - producto solo agregando otro grupo (para el caso del ejemplo ser&amp;iacute;a @ProductoActual) en el orden que se necesite y as&amp;iacute; generar todos los grupos necesarios&lt;/p&gt;
&lt;p&gt;Los resultados:&lt;/p&gt;
&lt;p&gt;


&lt;/p&gt;
&lt;table align="center" width="50%" cellpadding="0" cellspacing="0" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;fecha&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;producto&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;venta&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;VentaAcumulada&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-01&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-02&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-03&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-04&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-05&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-06&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-07&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-08&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-09&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-10&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-11&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-01&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-02&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-03&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-04&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-05&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-06&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-07&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-08&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-09&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2011-09-11&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Para que &amp;eacute;sta soluci&amp;oacute;n funcione, los datos deben estar previamente ordenados (por producto y fecha)&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda, &lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=202648" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Conteo de Filas de cada una de las tablas de la base de datos</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2012/01/05/code-conteo-de-filas-de-cada-una-de-las-tablas-de-la-base-de-datos.aspx" /><id>/blogs/fangarita/archive/2012/01/05/code-conteo-de-filas-de-cada-una-de-las-tablas-de-la-base-de-datos.aspx</id><published>2012-01-06T01:20:00Z</published><updated>2012-01-06T01:20:00Z</updated><content type="html">&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;&lt;strong&gt;Conteo de Filas de cada tabla&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;Haciendo diagn&amp;oacute;stico de las bases de datos, realizando seguimientos al crecimiento del n&amp;uacute;mero de registros y en fin para conocer el n&amp;uacute;mero de registros en todas las tablas existen varias t&amp;eacute;cnicas pero existen unas mejores que otras y a contiuaci&amp;oacute;n se presentar&amp;aacute;n:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;Una de las aproximaciones es usar uno de los procedimientos almacenados m&amp;aacute;s pr&amp;aacute;cticas que tiene TSql sp_MSforeachtable la cual nos permite ejecutar alg&amp;uacute;n tipo de instrucci&amp;oacute;n para cada una de las tablas de la base de datos, incluso admite filtros&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;exec sp_MSforeachtable &amp;#39;select &amp;#39;&amp;#39;?&amp;#39;&amp;#39; TableName, count(*) Cnt from ?&amp;#39;;&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;El asunto con esta soluci&amp;oacute;n es que se genera un resultset para cada una de las tablas (es decir, no es un solo resultado, sino uno por cada tabla) lo cual para cosas como un reporte son complicadas de manejar.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;Entonces la siguiente aproximaci&amp;oacute;n ser&amp;iacute;a desarrollar un procedimiento almacenado que genere la consulta y luego la una y me presente un solo resultado, algo como:&lt;/span&gt;&lt;/p&gt;
&lt;pre&gt;declare @tempTable table
(
    TableSchema nvarchar(256),
    TableName nvarchar(256),
    Cnt bigint
);

declare @sql nvarchar(4000);
declare @tableSchema nvarchar(256);
declare @tableName nvarchar(256);
declare @columnName sysname;
declare @cnt bigint;

declare tableCursor cursor for
    select TABLE_SCHEMA, TABLE_NAME from INFORMATION_SCHEMA.TABLES
    where TABLE_TYPE = &amp;#39;BASE TABLE&amp;#39;;

open tableCursor;

fetch next from tableCursor into @tableSchema, @tableName;

while @@FETCH_STATUS = 0
begin
    set @sql = &amp;#39;select @cnt = COUNT(*) from [&amp;#39; + @tableSchema + &amp;#39;].[&amp;#39; + @tableName + &amp;#39;]&amp;#39;;

    exec sp_executesql @sql, N&amp;#39;@cnt bigint output&amp;#39;, @cnt = @cnt output;

    insert into @tempTable select @tableSchema, @tableName, @cnt;

    fetch next from tableCursor into @tableSchema, @tableName;
end;

close tableCursor;
deallocate tableCursor;

select * from @tempTable;&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;Por supuesto esta soluci&amp;oacute;n tiene varios inconvenientes, para empezar usa un cursor para leer el listado de tablas de la consulta estandar INFORMATION_SCHEMA, segundo usa un sql din&amp;aacute;mico para armar poco a poco la consulta que se desea ejecutar y&amp;nbsp; algo que no se ve a simple vista y es la necesidad de ejecutar COUNT para cada una de las tablas, por lo cual &amp;eacute;sta no es la soluci&amp;oacute;n adecuada tampoco&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;Ahora veremos c&amp;oacute;mo podemos encontrar el conteo y de paso saber cual es la tabla que cuenta con mayor cantidad de registros&lt;/span&gt;&lt;/p&gt;
&lt;table width="100%" cellpadding="0" cellspacing="0" border="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="font-family:Arial;color:#ffffff;font-size:x-small;"&gt;Sql 2000&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="font-family:Arial;color:#ffffff;font-size:x-small;"&gt;Sql 2005+&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
&lt;pre&gt;SELECT OBJECT_NAME(id),rowcnt
FROM SYSINDEXES
WHERE OBJECTPROPERTY(id,&amp;rsquo;isUserTable&amp;rsquo;)=1 AND indid &amp;lt; 2
ORDER BY rowcnt DESC&lt;/pre&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;pre&gt;select sc.name +&amp;#39;.&amp;#39;+ ta.name
,sum(pa.rows) -- Valor aproximado
from sys.tables ta
inner join sys.partitions pa
on pa.object_id = ta.object_id
inner join sys.schemas sc
on ta.schema_id = sc.schema_id
where ta.is_ms_shipped = 0	AND pa.index_id IN (1,0)
group by sc.name,ta.name
ORDER BY sum(pa.rows) DESC&lt;/pre&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span style="font-family:Arial;font-size:x-small;"&gt;Sql Server crea estad&amp;iacute;sticas para cada tabla lo que le permite optimizar las consultas que ejecutamos por lo que podemos usar estas estad&amp;iacute;sticas para obtener &amp;eacute;ste dato, tambi&amp;eacute;n, analizar la consulta, observamos que se tiene en cuenta si la tabla est&amp;aacute; particionada y asimismo se consideran los esquemas para que la informaci&amp;oacute;n quede completa&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda, &lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=202626" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Pivote dinámico con sql server</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2012/01/02/code-pivote-din-225-mico-con-sql-server.aspx" /><id>/blogs/fangarita/archive/2012/01/02/code-pivote-din-225-mico-con-sql-server.aspx</id><published>2012-01-02T15:02:00Z</published><updated>2012-01-02T15:02:00Z</updated><content type="html">&lt;p&gt;&lt;strong&gt;Pivotes Din&amp;aacute;micos&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;En muchas ocaciones tenemos informaci&amp;oacute;n en filas y queremos convertirlas en columnas, &amp;eacute;sto se presenta especialmente en escenarios de an&amp;aacute;lisis en donde tener la informaci&amp;oacute;n en colunas es un requerimiento. &lt;/p&gt;
&lt;p&gt;Revisemos el ejemplo que presenta &lt;a href="http://msdn.microsoft.com/es-co/library/ms177410.aspx"&gt;MSDN&lt;/a&gt; en su documentaci&amp;oacute;n&lt;/p&gt;
&lt;p&gt;Si tenemos una consulta:&lt;/p&gt;
&lt;pre&gt;USE AdventureWorks2008R2 ;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost 
FROM Production.Product
GROUP BY DaysToManufacture;
&amp;nbsp;
&lt;/pre&gt;
&lt;p&gt;La cual arroja los siguiente resultados&lt;/p&gt;
&lt;p&gt;
&lt;table width="100%" border="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;DaysToManufacture&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;AverageCost &lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a&gt;0&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a&gt;5.0885&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a&gt;1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a&gt;223.88&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a&gt;2&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a&gt;359.1082&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;949.4105&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;y queremos verla en columnas&lt;/p&gt;
&lt;p&gt;
&lt;table width="100%" border="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;Cost_Sorted_By_Production_Days&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;0&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;1&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;2&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;3&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#000080"&gt;&lt;b&gt;&lt;span style="color:#ffffff;"&gt;4&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AverageCost&lt;/td&gt;
&lt;td&gt;5.0885&lt;/td&gt;
&lt;td&gt;223.88&lt;/td&gt;
&lt;td&gt;359.1082&lt;/td&gt;
&lt;td&gt;NULL&lt;/td&gt;
&lt;td&gt;949.4105&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;Debemos usar PIVOT&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;SELECT &amp;#39;AverageCost&amp;#39; AS
Cost_Sorted_By_Production_Days, [0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost FROM Production.Product) AS SourceTable&lt;br /&gt;
PIVOT
(AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;&lt;br /&gt;
&lt;/pre&gt;
&lt;p&gt;Revisando la sintaxis de la consulta tenemos que debemos definir una a una las columnas que deseamos obtener con la consulta y que &amp;eacute;stas correspondan al Valor que queremos poner en esa columna, es decir, para cero (0) d&amp;iacute;as de manufactura debemos crear una columan con el nombre 0 para que se asocie el valor que se tiene para esa columna, y se observa tambi&amp;eacute;n que se debe incluir una funci&amp;oacute;n de agregaci&amp;oacute;n para crear un contexto para cada celda en el momento de poner el valor en la columna, esto es clave para poder generar el pivote.&lt;/p&gt;
&lt;p&gt;Si se ha trabajado anteriormente con tablas din&amp;aacute;micas se ver&amp;aacute; que el comportamiento es similar tan solo debemos escribir nosotros mismos la consulta&lt;/p&gt;
&lt;p&gt;EN SQL 2000&lt;/p&gt;
&lt;p&gt;Ac&amp;aacute; tenemos una idea de c&amp;oacute;mo se podr&amp;iacute;a solucionar en Sql 2000, algunas de las funciones que se presentan en &amp;eacute;sta soluci&amp;oacute;n pronto ser&amp;aacute; descontinuadas en las futuras versiones de SQL &lt;/p&gt;
&lt;pre&gt;use AdventureWorks2008R2;
go

SELECT  
  [No. Sales per year]=CASE WHEN row IS NULL THEN &amp;#39;Sum&amp;#39;  
                   ELSE CONVERT(VARCHAR(80),[row]) END , 
  [1996] =SUM( CASE col WHEN &amp;#39;2005&amp;#39; THEN data ELSE 0 END ), 
  [1997] =SUM( CASE col WHEN &amp;#39;2006&amp;#39; THEN data ELSE 0 END ), 
  [1998] =SUM( CASE col WHEN &amp;#39;2007&amp;#39; THEN data ELSE 0 END ), 
  [Total]= SUM( data ) 
FROM  
   (SELECT [row]=P.firstname+&amp;#39; &amp;#39;+ P.lastname,  
           [col]=YEAR(SOH.OrderDate),  
           [data]=COUNT(*) 
    FROM Sales.SalesPerson SP INNER JOIN Sales.SalesOrderHeader SOH ON (SP.BusinessEntityID=SOH.SalesPersonID)  
    inner join HumanResources.Employee E ON SP.BusinessEntityID = E.BusinessEntityID 
    inner join Person.Person P ON E.BusinessEntityID = P.BusinessEntityID 
    GROUP BY P.firstname+&amp;#39; &amp;#39;+ P.lastname, YEAR(SOH.OrderDate) 
    )f 
GROUP BY row WITH ROLLUP 
ORDER BY GROUPING(row),total DESC
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;IDEAS&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Siempre que aprendemos algo se nos ocurren mas ideas, tales como: Qu&amp;eacute; pasa si se tienen d&amp;iacute;as de manufactura diferentes? qu&amp;eacute; pasa si quiero una columna para cada uno de esos d&amp;iacute;as, que pasa si lo hacemos por producto? por pais? qu&amp;eacute; pasa si cada uno de ellos tiene un comportamiento diferente?&lt;/p&gt;
&lt;p&gt;Muchas de esas preguntas se responden realizando un pivote con columnas din&amp;aacute;micas, es decir, al contrario de la sintaxis normal en donde debemos definir cada columna, que se interprete y de obtengan todas las columnas que necesito sin necesidad de definirlas una a una&lt;/p&gt;
&lt;p&gt;&lt;b&gt;CONSULTA DIN&amp;Aacute;MICA&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;use AdventureWorks2008R2;
go

declare @columnas varchar(max)

set @columnas = &amp;#39;&amp;#39;

select @columnas =  coalesce(@columnas + &amp;#39;[&amp;#39; + cast(DaysToManufacture as varchar(12)) + &amp;#39;],&amp;#39;, &amp;#39;&amp;#39;)
FROM (select distinct DaysToManufacture from Production.Product) as DTM

set @columnas = left(@columnas,LEN(@columnas)-1)

DECLARE @SQLString nvarchar(500);

set @SQLString = N&amp;#39;
SELECT *
FROM
(SELECT DaysToManufacture, StandardCost 
    FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN (&amp;#39; + @columnas + &amp;#39;)
) AS PivotTable;&amp;#39;

EXECUTE sp_executesql @SQLString
&lt;/pre&gt;
&lt;p&gt;Pero esta soluci&amp;oacute;n tiene el inconveniente de tener que lidiar con consultas Ad-Hoc (Din&amp;aacute;micas) que asocian posibles problemas de seguridad y rendimiento a la soluci&amp;oacute;n, esta soluci&amp;oacute;n as&amp;iacute; como la dem&amp;aacute;s que se puedan implementar debe considerar d&amp;oacute;nde se van a usar, posiblemente sea mas eficiente realizar el pivote en reporting services (Matriz) que en Sql, esto debe evaluarse para cada y depende de lo que se quiera realizar&lt;/p&gt;
&lt;p&gt;&lt;b&gt;OPCION CTE - Nombres de columna din&amp;aacute;micos&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Para 2005 o superior existe una alternativa para facilitar, mas no soluciona del todo el problema y es crear una consulta que asigna valores (n&amp;uacute;meros a las columnas) facilitando la construcci&amp;oacute;n final de la consulta. En este caso queremos pivotear por el nombre del mes, pero supongamos que el rango que damos en la primera consulta cambia, entonces los nombre de las columnas (Nombre del mes) no podr&amp;iacute;an ser usados. &lt;/p&gt;
&lt;p&gt;Por ejemplo si enviamos como par&amp;aacute;metro el primero de agosto,&amp;nbsp; hasta el 31 de diciembre o si enviamos el 1 de enero al 30 de junio, tendr&amp;iacute;amos que cambiar constantemente la consulta o presentar todos los meses, para solucionar esto tenemos el siguiente ejemplo&lt;/p&gt;
&lt;pre&gt;use AdventureWorksDW2008R2;
go

;With monthyears as (
SELECT DISTINCT SpanishMonthName as CalendarMonthYearName, MonthNumberOfYear as MonthOfYear,CalendarYear
      FROM dbo.DimDate 
      WHERE DateKey &amp;gt; @FechaInicio AND DateKey &amp;lt; @FechaFinal
),
CalMonthYears AS
(
SELECT CalendarMonthYearName AS &amp;#39;CalendarMonthYearName&amp;#39;,
      MonthOfYear,
      CalendarYear,
      &lt;b&gt;ROW_NUMBER() OVER (ORDER BY CalendarYear DESC) AS &amp;#39;YearMonthNum&amp;#39;&lt;/b&gt;  
      FROM monthyears
)
SELECT ProductKey,
      [1],[2],[3],[4],[5],[6]
FROM
(
-- your query to get your data, pivot this data
SELECT YearMonthNum,s.ProductKey,
      SUM(OrderQuantity) AS &amp;#39;Quantity&amp;#39;
      FROM FactResellerSales s
      INNER JOIN dbo.DimDate d ON s.OrderDateKey = d.DateKey
      INNER JOIN CalMonthYears cmy ON d.SpanishMonthName = cmy.CalendarMonthYearName
GROUP BY YearMonthNum,s.ProductKey
) AS SourceTable
PIVOT
(
SUM(Quantity)
FOR YearMonthNum IN (
     &lt;b&gt; [1],[2],[3],[4],[5],[6]&lt;/b&gt;
      )
) AS PivotTable&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=202560" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Calcular Edad a cualquier fecha</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/10/03/code-calcular-edad-a-cualquier-fecha.aspx" /><id>/blogs/fangarita/archive/2011/10/03/code-calcular-edad-a-cualquier-fecha.aspx</id><published>2011-10-04T00:36:00Z</published><updated>2011-10-04T00:36:00Z</updated><content type="html">&lt;p&gt;Este problema normalmente se soluciona del lado del cliente (Reporte, Aplicaci&amp;oacute;n) pero algunas ocaciones necesitamos presentarlo en algunas consultas por lo que la siguiente funci&amp;oacute;n puede ser pr&amp;aacute;ctica en varios escenarios&lt;/p&gt;
&lt;p&gt;Tomemos como ejemplo las siguientes fechas (obs&amp;eacute;rvese especialmente la &amp;uacute;ltima fecha que muestra el n&amp;uacute;mero de d&amp;iacute;a siguiente, diez a&amp;ntilde;os) y veamos c&amp;oacute;mo las funciones tradicionales muestran la diferencia en a&amp;ntilde;os, pero el c&amp;aacute;lculo no es correcto para la edad del usuario, incluso en la segunda aproximaci&amp;oacute;n tratando de solucionarlo por meses tampoco obtenemos el resultado esperado.&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;declare &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;@Fechas &lt;span style="color:#0000ff;"&gt;table &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;FechaNacimiento &lt;span style="color:#0000ff;"&gt;date&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;declare&lt;/span&gt; @hoy &lt;span style="color:#0000ff;"&gt;date&lt;br /&gt;set&lt;/span&gt; @hoy &lt;span style="color:#808080;"&gt;=&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:#808080;"&gt;()&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;insert&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @Fechas &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;&amp;#39;1978-05-20&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;insert&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @Fechas &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;&amp;#39;1963-01-14&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;insert&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @Fechas &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;&lt;span style="color:#ff00ff;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;yyyy&lt;span style="color:#808080;"&gt;,-&lt;/span&gt;10&lt;span style="color:#808080;"&gt;,&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;DATEADD&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;dd&lt;span style="color:#808080;"&gt;,&lt;/span&gt;1&lt;span style="color:#808080;"&gt;,&lt;/span&gt;@hoy&lt;span style="color:#808080;"&gt;)))&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;select&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;span style="color:#808080;"&gt;*&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; @Fechas &lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;
&lt;p&gt;select &lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#ff00ff;"&gt;DATEDIFF&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;yyyy&lt;span style="color:#808080;"&gt;,&lt;/span&gt;FechaNacimiento&lt;span style="color:#808080;"&gt;,&lt;/span&gt; @hoy&lt;span style="color:#808080;"&gt;),&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;cast&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;&lt;span style="color:#ff00ff;"&gt;DATEDIFF&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;mm&lt;span style="color:#808080;"&gt;,&lt;/span&gt; FechaNacimiento&lt;span style="color:#808080;"&gt;,&lt;/span&gt; @hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;/&lt;/span&gt; 12 &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; @Fechas&lt;/p&gt;
&lt;p&gt;Obtendremos resultados como (dependiendo de la fecha en que se ejecute el script, dado que toma la fecha actual del sistema):&lt;/p&gt;
&lt;p&gt;
&lt;table width="100%" border="0" style="BORDER-COLLAPSE:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#808080"&gt;&lt;b&gt;Edad Esperada&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#808080"&gt;&lt;b&gt;Diferencia A&amp;ntilde;os&lt;/b&gt;&lt;/td&gt;
&lt;td bgcolor="#808080"&gt;&lt;b&gt;Diferencia Meses&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;33.416666&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;48.750000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;10.000000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;Ahora la soluci&amp;oacute;n propuesta para &amp;eacute;ste problema es crear una funci&amp;oacute;n que lo resuelva retornando el valor adecuado, incluso para fechas diferentes a la actual (se puede enviar como par&amp;aacute;metro la fecha a la que quiero calcular la edad)&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt; &lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;
&lt;p&gt;create&amp;nbsp;&lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; ObtenerEdad&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@FechaNacimiento &lt;span style="color:#0000ff;"&gt;date&lt;/span&gt;&lt;span style="color:#808080;"&gt;,&lt;/span&gt; @AFecha &lt;span style="color:#0000ff;"&gt;date&lt;/span&gt; &lt;span style="color:#808080;"&gt;=&lt;/span&gt; &lt;span style="color:#808080;"&gt;null)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;returns&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;int&lt;br /&gt;Begin&lt;br /&gt;&lt;br /&gt;declare&lt;/span&gt; @hoy &lt;span style="color:#0000ff;"&gt;date&lt;/span&gt;&lt;span style="color:#808080;"&gt;,&lt;/span&gt; @Edad &lt;span style="color:#0000ff;"&gt;int&lt;br /&gt;if&lt;/span&gt; @hoy &lt;span style="color:#808080;"&gt;is&lt;/span&gt; &lt;span style="color:#808080;"&gt;null&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt; @hoy &lt;span style="color:#808080;"&gt;=&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;GETDATE&lt;/span&gt;&lt;span style="color:#808080;"&gt;()&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt; @hoy &lt;span style="color:#808080;"&gt;=&lt;/span&gt; @AFecha&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;
&lt;p&gt;set&amp;nbsp;&lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;@Edad &lt;span style="color:#808080;"&gt;=&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;CASE&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;WHEN&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;MONTH&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@FechaNacimiento&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;MONTH&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;THEN &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;&lt;span style="color:#ff00ff;"&gt;YEAR&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;br /&gt;&lt;span style="color:#808080;"&gt;&amp;nbsp;-&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;YEAR&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@FechaNacimiento&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;-&lt;/span&gt; 1&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;WHEN&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;MONTH&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;=&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;MONTH&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@FechaNacimiento&lt;span style="color:#808080;"&gt;)&lt;/span&gt;&amp;nbsp;&lt;br /&gt;&lt;span style="color:#808080;"&gt;&amp;nbsp;AND&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;DAY&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@FechaNacimiento&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;DAY&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;THEN&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;YEAR&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;-&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;YEAR&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@FechaNacimiento&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;br /&gt;&lt;span style="color:#808080;"&gt;&amp;nbsp;-&lt;/span&gt; 1 &lt;span style="color:#0000ff;"&gt;ELSE&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;YEAR&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;-&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;YEAR&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;@FechaNacimiento&lt;span style="color:#808080;"&gt;) &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;END&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; @Edad&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;End&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;go&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;/span&gt;&lt;/span&gt;Si intento de nuevo con los valores ingresados inicialmente obtenendr&amp;eacute; la edad correcta en cada caso &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;span style="color:#0000ff;"&gt;select &lt;/span&gt;dbo&lt;span style="color:#808080;"&gt;.&lt;/span&gt;ObtenerEdad&lt;span style="color:#808080;"&gt;(&lt;/span&gt;FechaNacimiento&lt;span style="color:#808080;"&gt;) as Edad, &lt;/span&gt;&lt;span style="color:#ff00ff;"&gt;DATEDIFF&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;yyyy&lt;span style="color:#808080;"&gt;,&lt;/span&gt;FechaNacimiento&lt;span style="color:#808080;"&gt;,&lt;/span&gt; @hoy&lt;span style="color:#808080;"&gt;),&lt;/span&gt; &lt;span style="color:#ff00ff;"&gt;cast&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;&lt;span style="color:#ff00ff;"&gt;DATEDIFF&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;mm&lt;span style="color:#808080;"&gt;,&lt;/span&gt; FechaNacimiento&lt;span style="color:#808080;"&gt;,&lt;/span&gt; @hoy&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;decimal&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;/span&gt; &lt;span style="color:#808080;"&gt;/&lt;/span&gt; 12&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; @Fechas&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;span style="font-size:x-small;"&gt;Espero sea de ayuda,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=200980" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Cómo numerar filas en SSIS</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/09/26/code-c-243-mo-numerar-filas-en-ssis.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="28001" href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.20.07.52/NumerarFilas.zip" /><id>/blogs/fangarita/archive/2011/09/26/code-c-243-mo-numerar-filas-en-ssis.aspx</id><published>2011-09-26T20:19:00Z</published><updated>2011-09-26T20:19:00Z</updated><content type="html">&lt;p&gt;Numerar Filas puede ser de gran ayuda para crear l&amp;oacute;gica en SSIS, para generarlas se pueden seguir los siguientes pasos&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Agregar un DataFLow Task&lt;/li&gt;
&lt;li&gt;Agregar un Origen de datos con una consulta a la que le queramos generar los n&amp;uacute;meros de fila&lt;/li&gt;
&lt;li&gt;Agregar un Script Component Agregar una Columna de Salida Llamada (para el ejemplo) &lt;em&gt;Numero&lt;/em&gt;, con un c&amp;oacute;digo similar al presentado a continuaci&amp;oacute;n:&lt;br /&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;
&lt;p&gt;public&lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;class&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#2b91af;font-size:x-small;"&gt;&lt;span style="color:#2b91af;font-size:x-small;"&gt;ScriptMain&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; : &lt;/span&gt;&lt;span style="color:#2b91af;font-size:x-small;"&gt;&lt;span style="color:#2b91af;font-size:x-small;"&gt;UserComponent&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;private&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;int&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; _RowNumber = 0;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;&lt;span style="font-size:x-small;"&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;public&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;override&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;void&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; Input0_ProcessInputRow(&lt;/span&gt;&lt;span style="color:#2b91af;font-size:x-small;"&gt;&lt;span style="color:#2b91af;font-size:x-small;"&gt;Input0Buffer&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; Row)&lt;br /&gt;{&lt;br /&gt;_RowNumber++;&lt;br /&gt;Row.Numero1 = _RowNumber;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;El c&amp;oacute;diigo generar&amp;aacute; el n&amp;uacute;mero de fila de acuerdo al ordenamiento actual&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;Se podr&amp;aacute; repetir el paso 3 para agregar el n&amp;uacute;mero de ordenamientos que sea necesario&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;Se agrega un paquete de ejemplo para realizar &amp;eacute;sta tarea y como parte del ejemplo se distribuyen los productos en pares e impares &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;Espero sea de ayuda,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=200752" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Info] Contadores de Rendimiento para diagnóstico y afinación de SqlServer</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/09/10/info-contadores-de-rendimiento-para-diagn-243-stico-y-afinaci-243-n-de-sqlserver.aspx" /><id>/blogs/fangarita/archive/2011/09/10/info-contadores-de-rendimiento-para-diagn-243-stico-y-afinaci-243-n-de-sqlserver.aspx</id><published>2011-09-10T21:46:00Z</published><updated>2011-09-10T21:46:00Z</updated><content type="html">&lt;p&gt;A continuaci&amp;oacute;n presento alguno de los contadores de rendimiento, pertenecientes a la instrumentaci&amp;oacute;n de SqlServer que ayudan al proceso de diagn&amp;oacute;stico y optimizaci&amp;oacute;n de SqlServer&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Performance.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Performance.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Performance-Counter.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Performance-Counter.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Performance-Counter.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En el gr&amp;aacute;fico se presenta el grupo de contadores de rendimiento, luego al abrirlo se presenta cada contador independiente y luego en la parte de abajo (si aplica) que es lo q se quiere medir&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Procesador&lt;/strong&gt; 
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Processor&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td width="1"&gt;Esperado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;%User Time&lt;/td&gt;
&lt;td&gt;SqlServer se ejecuta en modo de Usuario. El modo privilegiado es usado por el Sistema operativo para acceder a los componentes de hardware. Este componente deber&amp;iacute;a presentar un valor mayor de 70%, si el valor es menor que esto se deben revisar los indicadores %privileged time y %processor time para verificar si existe alg&amp;uacute;n tipo de problema con el procesador&lt;/td&gt;
&lt;td width="1"&gt;&amp;gt;70%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;%Privileged Time&lt;/td&gt;
&lt;td&gt;El sistema operativo mueve los hilos al modo de acceso privilegiado para acceder servicios de Hardware. Este contador debe tener un valor menor a 20%.&lt;/td&gt;
&lt;td width="1"&gt;&amp;lt;20%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;%Processor Time&lt;/td&gt;
&lt;td&gt;Presenta el porcentaje de tiempo usado por la CPU en un periodo de tiempo. Idealmente debe ser menor que 70%.&lt;/td&gt;
&lt;td width="1"&gt;&amp;lt;70%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Interrupts/Sec&lt;/td&gt;
&lt;td&gt;Es el promedio de incidentes por segundo, al cual el procesador recibi&amp;oacute; y proces&amp;oacute; interrupciones de Hardware&lt;/td&gt;
&lt;td width="1"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;System&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Esperado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Processor Queue Length&lt;/td&gt;
&lt;td&gt;Es el n&amp;uacute;mero de hilos que espearan a ser procesados. Este contador por valor general divido por el n&amp;uacute;mero de n&amp;uacute;cleos disponibles. Deber&amp;iacute;a ser menor que 2&lt;/td&gt;
&lt;td&gt;&amp;lt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disco&lt;/strong&gt;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Physical Disk&lt;/td&gt;
&lt;td width="80%"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="1"&gt;Esperado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Current Queue Length&lt;/td&gt;
&lt;td width="80%"&gt;Un tama&amp;ntilde;o sostenido de una cola de disco presenta un posible problema con el subsistema de I/O.&lt;/td&gt;
&lt;td width="1"&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average Queue Length&lt;/td&gt;
&lt;td width="80%"&gt;Si el promedio de longitud de la cola es mayor que 2 indica que existe un problema potencial con el subsistea de IO, esto tambien puede deberse a un indicador disk sec/read y disk sec/write alto.&lt;/td&gt;
&lt;td width="1"&gt;&amp;lt;=2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disk Sec/Read
&lt;p&gt;Disk Sec/Writes&lt;/p&gt;
&lt;/td&gt;
&lt;td width="80%"&gt;Ninguno de estos contadores deber&amp;iacute;a tener un valor superior a 15ms en condiciones normales. Valores continuos sobre 20ms puede indicar un problema en el disco o sobrecarga del sistema o alto fraccionamiento del disco.
&lt;p&gt;Bajo estas condiciones se pueden considerar las siguientes alternativas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mover los archivos de base de datos a discos adicionales&lt;/li&gt;
&lt;li&gt;Crear grupos de archivos en diferentes discos y pasar algunas tablas a cada uno de esos discos&amp;nbsp; (pueden tener difernte RAID) lo cual puede influir notablemente en el desempe&amp;ntilde;o&lt;/li&gt;
&lt;li&gt;Revisar los &amp;iacute;ndices de las tablas&lt;/li&gt;
&lt;li&gt;Revisar los contadores de CPU y memoria con el fin de identificar otros cuellos de Botella&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td width="1"&gt;&amp;lt;=15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;Memory/Cache&lt;/b&gt;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Memory&lt;/td&gt;
&lt;td width="80%"&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Page Faults/Sec:&lt;/td&gt;
&lt;td width="80%"&gt;Los fallos de p&amp;aacute;gina ocurren cuando se busca una p&amp;aacute;gina en memoria y no se encuentra. Existen 2 tipos de fallos de p&amp;aacute;gina:
&lt;p&gt;&lt;a name="Fuertes_(Hard)_"&gt;Fuertes (Hard) &lt;/a&gt;: Requiere acceso a disco&lt;/p&gt;
&lt;p&gt;Suaves (Soft).&amp;nbsp; La p&amp;aacute;gina buscada est&amp;aacute; en alguna otra parte de la memoria&lt;/p&gt;
&lt;p&gt;Un alto n&amp;uacute;mero de fallos de p&amp;aacute;gina por segundo indica que existe un problema con la memoria usada por Sql Server. Usando este contador junto con SqlServer:MemoryManager se puede determinar si existe algun tipo de presi&amp;oacute;n sobre la memoria&lt;/p&gt;
&lt;p&gt;Bajo estas condiciones puede considerarse:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Revisar los procedimientos y las pr&amp;aacute;cticas usadas para el desarrollo de los mismos&lt;/li&gt;
&lt;li&gt;Aumentar la memoria del servidor &lt;/li&gt;
&lt;li&gt;Revisar el espacio en disco disponible en donde se ubiquen los temporales del sistema operativo&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Pages/Sec&lt;/td&gt;
&lt;td width="80%"&gt;Este contador es valor real de fallos &lt;a href="http://geeks.ms/controlpanel/blogs/posteditor.aspx?SelectedNavItem=NewPost#Fuertes_(Hard)_"&gt;Fuertes de p&amp;aacute;ginas&lt;/a&gt; y debe ser usado en correlaci&amp;oacute;n con Page Faults/Sec y SQL Server memory Manager para revisar la presi&amp;oacute;n sobre la memoria&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;SQL Server&lt;/strong&gt;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Access Methods&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Forwarded Records/Sec&lt;/td&gt;
&lt;td&gt;Numero de registros tra&amp;iacute;dos usando punteros de registros, es decir, cuando los registros tienen espacios vac&amp;iacute;os entre ellos o cuando el tama&amp;ntilde;o del registro no queda ajustado al tama&amp;ntilde;o de una p&amp;aacute;gina, esta situaci&amp;oacute;n puede presentarse cuando se inicia con un registro corto y se actualiza el dato quedando parte de &amp;eacute;ste en otra p&amp;aacute;gina lo que requiere la generaci&amp;oacute;n de un puntero para saber en qu&amp;eacute; lugar est&amp;aacute; la otra parte del registro.
&lt;p&gt;Esto se puede evitar siguiendo los siguientes pasos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ser cuidadoso al determinar cuales de las columnas permiten o no nulos&lt;/li&gt;
&lt;li&gt;Usar valores por defecto (para evitar el uso de nulos)&lt;/li&gt;
&lt;li&gt;Usar char en lugar de Varchar cuando sea posible&lt;/li&gt;
&lt;li&gt;Manejar un esquema de normalizaci&amp;oacute;n en donde el n&amp;uacute;mero de campos sea menos (Soluciones OLTP)&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Full Scans/Sec&lt;/td&gt;
&lt;td&gt;Se realiza una lectura completa de una Tabla o de un &amp;iacute;ndice. Esto puede ser causado por el uso indebido de &amp;iacute;ndices.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Page Splits/Sec&lt;/td&gt;
&lt;td&gt;Fraccionamiento sobre las p&amp;aacute;ginas de los &amp;iacute;ndices. Este indicador est&amp;aacute; asociado a las p&amp;aacute;ginas hoja del Arbol de &amp;iacute;ndices que no se almacenan conitnuamente lo que lleva a su fraccionamiento en disco. Esto se puede evitar configurando apropiadamente &lt;a href="http://geeks.ms/controlpanel/blogs/posteditor.aspx?SelectedNavItem=NewPost#Fill_Factor"&gt;Fill Factor&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Memory Manager&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Memory Grants Pending&lt;/td&gt;
&lt;td&gt;Memoria que se necesita para procesar cada una de las peticiones de los usuarios. Si no se dispone de memoria suficiente entonces el proceso debe esperar a que se le sea asignada para su ejecuci&amp;oacute;n, lo que por supuesto impacta el desempe&amp;ntilde;o de la consulta o procedimiento en ejecuci&amp;oacute;n
&lt;p&gt;Para evitarlo se pueden seguir los siguientes pasos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agregar mas memoria al servidor&lt;/li&gt;
&lt;li&gt;Asignando mas memoria a SqlServer&lt;/li&gt;
&lt;li&gt;Creando &amp;Iacute;ndices apropiados&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Buffer Manager&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;Esperado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Buffer Cache Hit Ratio&lt;/td&gt;
&lt;td&gt;Porcentaje del tiempo en que las p&amp;aacute;ginas solicitadas est&amp;aacute;n ya en memoria. Idealmente debe mantenerse sobre 99%, si es menor que 95% indica que SqlServer no tiene suficiente memoria y que agregar m&amp;aacute;s memoria al servidor, asignada a SqlServer, ser&amp;iacute;a muy beficioso&lt;/td&gt;
&lt;td&gt;&amp;gt;99%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Checkpoints/Sec&lt;/td&gt;
&lt;td&gt;Paginas escritas a disco durante el proceso de &lt;a href="http://geeks.ms/controlpanel/blogs/posteditor.aspx?SelectedNavItem=NewPost#CheckPoints"&gt;CheckPoint&lt;/a&gt;. Se identifica presi&amp;oacute;n sobre la memoria si el contador tiene un valor superior a 300 Segundos&lt;/td&gt;
&lt;td&gt;&amp;lt;300s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Lazy Writes/Sec&lt;/td&gt;
&lt;td&gt;Paginas escritas a disco durante el proceso &lt;a href="http://geeks.ms/controlpanel/blogs/posteditor.aspx?SelectedNavItem=NewPost#Lazy_Writer"&gt;LazyWriter&lt;/a&gt; (Escribe las p&amp;aacute;ginas en segundo plano al disco). Se identifica presi&amp;oacute;n sobre la memoria si el contador tiene un valor superior a 300 Segundos&lt;/td&gt;
&lt;td&gt;&amp;lt;300s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Page Life Expectancy&lt;/td&gt;
&lt;td&gt;Este es uno de los principales contadores para identificar presi&amp;oacute;n sobre la memoria. Determina el tiempo en segundos en el que la p&amp;aacute;gina reside en el Cach&amp;eacute; de SqlServer. Si el valor es bajo indica los siguientes problemas: 
&lt;ul&gt;
&lt;li&gt;El Cach&amp;eacute; es Frio (Revisar informaci&amp;oacute;n sobre Fallos de P&amp;aacute;gina Page Faults)&lt;/li&gt;
&lt;li&gt;Problemas de Memoria&lt;/li&gt;
&lt;li&gt;Falta de creaci&amp;oacute;n de &amp;iuml;ndices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Si Checkpoints/Sec, Lazy Writes/Sec y Page life expectancy juntos es menor a 300 Segundos entonces indica que la causa es la falta de memoria y que se debe agregar m&amp;aacute;s memoria al servidor&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Databases&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Transactions/Sec&lt;/td&gt;
&lt;td&gt;Indica el n&amp;uacute;mero de transacciones que ocurren por sengundo en el servidor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;General StatisticsCounters&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;User Connections&lt;/td&gt;
&lt;td&gt;N&amp;uacute;mero de conexiones hechas a SqlServer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Latches&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Average Latch wait Time&lt;/td&gt;
&lt;td&gt;Son objetos livianos de sincronizaci&amp;oacute;n. No se mantienen durante la duraci&amp;oacute;n de la transacci&amp;oacute;n. T&amp;iacute;picamente se usan cuando se transfieren filas a memoria, mientras se contolan modificaciones a las filas, etc.
&lt;p&gt;Un valor alto puede indicar alg&amp;uacute;n problema con el subsistema de Memoria&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table width="100%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Locks&lt;/td&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="20%"&gt;Average Wait Time(ms)&lt;br /&gt;Lock Wait time(ms)&lt;br /&gt;Lock waits/Sec&lt;/td&gt;
&lt;td&gt;Los contadores relacionados a los bloqueos que mantiene SqlServer en un momento determinado de las transacciones. Las transacciones deben ser tan cortas como sea posible y por lo tanto deber&amp;iacute;a mantener bloqueos la menor cantidad de tiempo posible para evitar para bloqueos a otros usaurios o procesos. Un Valor alto para cualquiera de estos contadores indica: 
&lt;ul&gt;
&lt;li&gt;Presi&amp;oacute;n sobre la memoria&lt;/li&gt;
&lt;li&gt;Problemas con el Disco&lt;/li&gt;
&lt;li&gt;&amp;Iacute;ndices inadecuados&lt;/li&gt;
&lt;li&gt;Dise&amp;ntilde;o inadecuado de tablas u objetos de SqlServer&lt;/li&gt;
&lt;li&gt;Inadecuada ubicaci&amp;oacute;n de los archivos de base de datos &lt;/li&gt;
&lt;li&gt;Uso indebido de los niveles de aislamiento de SqlServer&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Los mencionados, son algunos de los contadores preferidos, aparte de esos pueden revisarse estos contadores:&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Object Name Counter Name&lt;br /&gt;SQL Statistics Compilations/sec&lt;br /&gt;SQL Statistics Recompilations/sec&lt;br /&gt;SQL Statistics Batch Requests/sec&lt;br /&gt;SQL Server: Buffer Manager Readahead pages/sec&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Algunas Definiciones&lt;/b&gt;&lt;/p&gt;
&lt;hr align="left" /&gt;
&lt;p&gt;&lt;a name="P&amp;aacute;ginas_Sucias"&gt;P&amp;aacute;ginas Sucias&lt;/a&gt;: P&amp;aacute;ginas que han entrado al cach&amp;eacute; y han sido modificadas, pero aun no se han escrito a disco. &lt;/p&gt;
&lt;p&gt;&lt;a name="CheckPoints"&gt;CheckPoints&lt;/a&gt;: Escribe todas las p&amp;aacute;ginas sucias a disco. Crea un punto al cual se garantiza que todas las p&amp;aacute;ginas han sido escritas a disco&lt;/p&gt;
&lt;p&gt;&lt;a name="Fill_Factor"&gt;Fill Factor&lt;/a&gt;: Factor por el cual crecen los archivos de base datos, cuando se espera una gran cantidad de nuevos registros en la base de datos se debe establecer un FillFactor alto con el fin que los datos no queden fragmentados y un FillFactor un poco menor en caso de ser utilizada en procesos de actualizaci&amp;oacute;n y solo consulta&lt;/p&gt;
&lt;p&gt;&lt;a name="Lazy_Writer"&gt;Lazy Writer&lt;/a&gt;:&amp;nbsp; es un proceso que elimina conjuntos de buffers viejos y no usaados de memoria (Los buffers que tienen cambios deben ser escritos de nuevo al disco antes que el buffer pueda ser reusado para una p&amp;aacute;gina diferente). &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=200429" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Cómo detectar los grupos de archivos que tiene cada tabla en la base de datos</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/09/07/code-c-243-mo-detectar-los-grupos-de-archivos-que-tiene-cada-tabla-en-la-base-de-datos.aspx" /><id>/blogs/fangarita/archive/2011/09/07/code-c-243-mo-detectar-los-grupos-de-archivos-que-tiene-cada-tabla-en-la-base-de-datos.aspx</id><published>2011-09-07T22:57:00Z</published><updated>2011-09-07T22:57:00Z</updated><content type="html">&lt;p&gt;&lt;span style="font-size:x-small;"&gt;
&lt;p&gt;En el art&amp;iacute;culo en el &lt;a href="http://geeks.ms/blogs/fangarita/archive/2011/01/17/info-optimizaci-243-n-de-consultas-parte-1-generalidades.aspx" title="Optimizaci&amp;oacute;n de consultas"&gt;art&amp;iacute;culo de optimizaci&amp;oacute;n de consultas&lt;/a&gt; se menciona como uno de los procesos de optimizaci&amp;oacute;n, la asignaci&amp;oacute;n de grupos de archivos a diferentes tables para utilizar mejor el hardware del servidor y hacer de las consultas un proceso mas veloz, para determinar cual son las tablas que son candidatas para pasarlas a otros grupos de archivos podemos usar:&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;select&lt;/span&gt; si&lt;span style="color:#808080;"&gt;.&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;rows&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;ConteoFilas&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;,&lt;/span&gt; SO&lt;span style="color:#808080;"&gt;.&lt;/span&gt;Name &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;Tabla&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;,&lt;/span&gt; SI&lt;span style="color:#808080;"&gt;.&lt;/span&gt;name &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;Nombre Indice&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;,&lt;/span&gt; SFG&lt;span style="color:#808080;"&gt;.&lt;/span&gt;groupname &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;Grupo de Archivos&amp;#39;&lt;/span&gt; &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;from &lt;/span&gt;&lt;span style="color:#008000;"&gt;sysobjects&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; SO &lt;span style="color:#808080;"&gt;join&lt;/span&gt; &lt;span style="color:#008000;"&gt;sysindexes&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; SI &lt;span style="color:#0000ff;"&gt;on &lt;/span&gt;SO&lt;span style="color:#808080;"&gt;.&lt;/span&gt;Id &lt;span style="color:#808080;"&gt;=&lt;/span&gt; SI&lt;span style="color:#808080;"&gt;.&lt;/span&gt;id &lt;span style="color:#808080;"&gt;join&lt;/span&gt; &lt;span style="color:#008000;"&gt;sysfilegroups&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; SFG &lt;span style="color:#0000ff;"&gt;on &lt;/span&gt;SI&lt;span style="color:#808080;"&gt;.&lt;/span&gt;GroupId &lt;span style="color:#808080;"&gt;=&lt;/span&gt; SFG&lt;span style="color:#808080;"&gt;.&lt;/span&gt;GroupId &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;order&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;by&lt;/span&gt; si&lt;span style="color:#808080;"&gt;.&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;rows&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;desc&lt;/span&gt;&lt;span style="color:#808080;"&gt;,&lt;/span&gt; SO&lt;span style="color:#808080;"&gt;.&lt;/span&gt;Name &lt;span style="color:#808080;"&gt;,&lt;/span&gt; SI&lt;span style="color:#808080;"&gt;.&lt;/span&gt;name&lt;span style="color:#808080;"&gt;,&lt;/span&gt; SFG&lt;span style="color:#808080;"&gt;.&lt;/span&gt;GroupName&lt;/p&gt;
&lt;p&gt;Las tablas que contengan un mayor n&amp;uacute;mero de registros son candidatas para hacer el paso a otro(s) grupos de archivo&lt;/p&gt;
&lt;span style="color:#0000ff;font-size:x-small;"&gt;
&lt;p&gt;select &lt;/p&gt;
&lt;span style="color:#0000ff;font-size:x-small;"&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;Esto nos devuelte el numero de filas y nombre de la tabla y el grupo de archivos al cual pertenece, en versiones como Standard &amp;eacute;ste puede ser uno de los pasos para lograr m&amp;aacute;s velocidad en tablas de hechos, tales como movimientos y registros paso a paso&lt;/span&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;si&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;rows&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;as&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;font-size:x-small;"&gt;&amp;#39;Rows&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;,&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SO&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;Name &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;as&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;font-size:x-small;"&gt;&amp;#39;Table&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;,&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SI&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;name &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;as&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;font-size:x-small;"&gt;&amp;#39;Index&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;,&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SFG&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;groupname &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;as&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#ff0000;font-size:x-small;"&gt;&amp;#39;Filegroup&amp;#39; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;from &lt;/span&gt;&lt;span style="color:#008000;font-size:x-small;"&gt;sysobjects&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;as &lt;/span&gt;&lt;span style="font-size:x-small;"&gt;SO &lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;join&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-size:x-small;"&gt;sysindexes&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;as&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SI &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;on&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SO&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;Id &lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;=&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SI&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;id &lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;join&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#008000;font-size:x-small;"&gt;sysfilegroups&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;as &lt;/span&gt;&lt;span style="font-size:x-small;"&gt;SFG &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;on&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SI&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;GroupId &lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;=&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SFG&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;GroupId&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;order&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;by&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; si&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;rows&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;font-size:x-small;"&gt;desc&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;,&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SO&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;Name &lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;,&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SI&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;.&lt;/span&gt;&lt;span style="font-size:x-small;"&gt;name&lt;/span&gt;&lt;span style="color:#808080;font-size:x-small;"&gt;,&lt;/span&gt;&lt;span style="font-size:x-small;"&gt; SFG.GroupName&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;
&lt;p&gt;Espero sea de ayuda&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=200394" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Cómo consultar los registros no asociados con otros registros de la misma tabla</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/09/06/code-c-243-mo-consultar-los-registros-no-asociados-con-otros-registros-de-la-misma-tabla.aspx" /><id>/blogs/fangarita/archive/2011/09/06/code-c-243-mo-consultar-los-registros-no-asociados-con-otros-registros-de-la-misma-tabla.aspx</id><published>2011-09-06T16:24:00Z</published><updated>2011-09-06T16:24:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;Detectar si un determinado usuario&amp;nbsp;tiene o no autorizaci&amp;oacute;n para realizar alguna tarea, detectar cuales de los &amp;iacute;tems no ha sido asociados a &amp;eacute;l es tan solo algunas de las aplicaciones para &amp;eacute;ste art&amp;iacute;culo. &lt;/p&gt;
&lt;p&gt;Como primera instancia tenemos una tabla de ejemplo, que se genera usando:&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;declare &lt;/span&gt;@t1 &lt;span style="color:#0000ff;"&gt;table &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;id &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt;&lt;span style="color:#808080;"&gt;,&lt;/span&gt; VALOR &lt;span style="color:#0000ff;"&gt;CHAR&lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;1&lt;span style="color:#808080;"&gt;))&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;
&lt;p&gt;insert into &lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;@t1 &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;1&lt;span style="color:#808080;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;A&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;insert&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @t1 &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;2&lt;span style="color:#808080;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;insert&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @t1 &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;3&lt;span style="color:#808080;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;C&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;insert&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @t1 &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;4&lt;span style="color:#808080;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;D&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;insert&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;into&lt;/span&gt; @t1 &lt;span style="color:#0000ff;"&gt;values &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;5&lt;span style="color:#808080;"&gt;,&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;&amp;#39;E&amp;#39;&lt;/span&gt;&lt;span style="color:#808080;"&gt;)&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;
&lt;p&gt;select &lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#808080;"&gt;*&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; @t1 &lt;/p&gt;
&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;table width="50%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#c0c0c0"&gt;id&lt;/td&gt;
&lt;td bgcolor="#c0c0c0"&gt;VALOR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;Queremos saber por cada uno de los valores en la columna Id, cuales de los valores en la columna VALOR no est&amp;aacute;n asociados con un Id&lt;/p&gt;
&lt;p&gt;Es decir que para el Id 1, los valores deben ser B,C,D,E&lt;/p&gt;
&lt;p&gt;La primera aproximaci&amp;oacute;n para saber cual de los VALORES est&amp;aacute; aplicado a cada uno de los Id es realizar un Cross Join&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="color:#0000ff;"&gt;
&lt;p&gt;SELECT &lt;/p&gt;
&lt;/span&gt;&lt;/span&gt;
&lt;p&gt;&lt;span style="color:#808080;"&gt;*&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; @t1 t1 &lt;span style="color:#808080;"&gt;cross&lt;/span&gt; &lt;span style="color:#808080;"&gt;join &lt;/span&gt;@t1 t2 &lt;/p&gt;
&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;table width="50%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#c0c0c0"&gt;id&lt;/td&gt;
&lt;td bgcolor="#c0c0c0"&gt;VALOR&lt;/td&gt;
&lt;td bgcolor="#c0c0c0"&gt;id&lt;/td&gt;
&lt;td bgcolor="#c0c0c0"&gt;VALOR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td bgcolor="#9bb4e6"&gt;1&lt;/td&gt;
&lt;td bgcolor="#9bb4e6"&gt;A&lt;/td&gt;
&lt;td bgcolor="#9bb4e6"&gt;1&lt;/td&gt;
&lt;td bgcolor="#9bb4e6"&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td bgcolor="#d7e0f4"&gt;1&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;A&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;2&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td bgcolor="#d7e0f4"&gt;1&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;A&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;3&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td bgcolor="#d7e0f4"&gt;1&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;A&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;4&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td bgcolor="#d7e0f4"&gt;1&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;A&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;5&lt;/td&gt;
&lt;td bgcolor="#d7e0f4"&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;Se nota en &amp;eacute;sta combinaci&amp;oacute;n que 1 ya est&amp;aacute; asociado con A en la fila &lt;span style="background-color:#9bb4e6;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;y notamos que en las columnas &lt;span style="background-color:#d7e0f4;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;nbsp;vemos que los valos con 1 no est&amp;aacute;n asociados&lt;/p&gt;
&lt;p&gt;Por lo que si creamos un condici&amp;oacute;n podemos eliminar los que ya est&amp;aacute;n asociados dejando solo los que NO est&amp;aacute;n asociados&lt;/p&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;SELECT &lt;/span&gt;t2&lt;span style="color:#808080;"&gt;.&lt;/span&gt;id&lt;span style="color:#808080;"&gt;,&lt;/span&gt; t1&lt;span style="color:#808080;"&gt;.&lt;/span&gt;VALOR &lt;span style="color:#0000ff;"&gt;from&lt;/span&gt; @t1 t1 &lt;span style="color:#808080;"&gt;cross join &lt;/span&gt;@t1 t2 &lt;span style="color:#0000ff;"&gt;where &lt;/span&gt;&lt;span style="color:#808080;"&gt;not&lt;/span&gt;&lt;span style="color:#0000ff;"&gt; &lt;/span&gt;&lt;span style="color:#808080;"&gt;(&lt;/span&gt;t1&lt;span style="color:#808080;"&gt;.&lt;/span&gt;id &lt;span style="color:#808080;"&gt;=&lt;/span&gt; t2&lt;span style="color:#808080;"&gt;.&lt;/span&gt;id &lt;span style="color:#808080;"&gt;and&lt;/span&gt; t2&lt;span style="color:#808080;"&gt;.&lt;/span&gt;VALOR &lt;span style="color:#808080;"&gt;=&lt;/span&gt; t2&lt;span style="color:#808080;"&gt;.&lt;/span&gt;VALOR &lt;span style="color:#808080;"&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;
&lt;table width="50%" border="1" style="border-collapse:collapse;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td bgcolor="#c0c0c0"&gt;id&lt;/td&gt;
&lt;td bgcolor="#c0c0c0"&gt;VALOR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=200379" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Como crear el esquema de un archivo Raw SSIS</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/08/26/code-como-crear-el-esquema-de-un-archivo-raw-ssis.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="5142" href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.20.00.07/Package3.zip" /><id>/blogs/fangarita/archive/2011/08/26/code-como-crear-el-esquema-de-un-archivo-raw-ssis.aspx</id><published>2011-08-26T16:45:00Z</published><updated>2011-08-26T16:45:00Z</updated><content type="html">&lt;p&gt;Importar&amp;nbsp;grandes vol&amp;uacute;menes de datos puede tomar mucho tiempo en SSIS si no se hace de la manera apropiada, y una de las principales t&amp;eacute;cnicas para lograr este prop&amp;oacute;sito es el uso de archivos Raw (Crudos), los cuales son archivos binarios de alt&amp;iacute;simo rendimiento que por sus caracter&amp;iacute;sticas permiten leer y escribir datos a alta velocidad haci&amp;eacute;ndolos ideales para ser el paso intermedio entre el origen y el destino de los datos (Stage).&lt;/p&gt;
&lt;p&gt;Para usarlos, sin embargo, debe crearse primero un archivo vac&amp;iacute;o que tenga el esquema de datos que vamos a utilizar posteriormente en nuestra soluci&amp;oacute;n, as&amp;iacute; que presento los pasos para crear este esquema usando un paquete que apoya dicha tarea:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Crear un nuevo paquete&lt;/li&gt;
&lt;li&gt;Agregar un Data Flow&lt;/li&gt;
&lt;li&gt;Agrear un Origen de Datos Ole Db&lt;/li&gt;
&lt;li&gt;Crear una consulta para el origen Ole Db que devuelva cero registros (&lt;strong&gt;top 0&lt;/strong&gt;) y que tenga los registros que deseamos incluir en el esquema del archivo raw&lt;br /&gt;select top 0&lt;br /&gt;cast(null as int) as Id,&lt;br /&gt;cast(null as varchar(50)) as Value&lt;/li&gt;
&lt;li&gt;Si es necesario, Agregar una transformaci&amp;oacute;n DataConversion para establecer el tipo de datos desedo para cada columna&lt;/li&gt;
&lt;li&gt;Agregar un Destino de Archivo Raw y seleccionar las columnas que se quieren en el archivo Raw&lt;/li&gt;
&lt;li&gt;Ejecutar el Paquete&lt;/li&gt;
&lt;li&gt;Usar el Archivo Raw&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Adjunto se encuentra un paquete de ejemplo para realizar &amp;eacute;sta tarea&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=200007" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Cómo Obtener los últimos Identity (Autonumérico) Insertados</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/06/10/code-obtener-los-250-ltimos-identity-insertados.aspx" /><id>/blogs/fangarita/archive/2011/06/10/code-obtener-los-250-ltimos-identity-insertados.aspx</id><published>2011-06-10T19:41:00Z</published><updated>2011-06-10T19:41:00Z</updated><content type="html">&lt;p&gt;Siempre buscando la optimizaci&amp;oacute;n de consultas debemos intentar siempre el uso de operaciones de conjunto sobre las operaciones fila a fila, &amp;eacute;ste es uno de los ejemplos en donde usando T-Sql podemos obtener los &amp;uacute;ltimos IDs generados a partir de la inserci&amp;oacute;n en una las tablas que tienen Identity, &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;strong&gt;DECLARE @output TABLE (id int)&amp;nbsp; &lt;span style="color:#668866;"&gt;--Tabla para capturar los IDs generados&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Insert into A (fname, lname) &lt;span style="color:#668866;"&gt;-- Tabla en la que insertaremos los datos&lt;/span&gt; &lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;OUTPUT inserted.ID INTO @output &lt;span style="color:#668866;"&gt;--Captura de los IDs generados con el uso de la palabra clave OUTPUT&lt;/span&gt;&lt;br /&gt;&lt;/strong&gt;&lt;strong&gt;SELECT fname, lname FROM B &lt;span style="color:#668866;"&gt;-- Consulta que trae los datos a insertar&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;strong&gt;select * from @output &lt;span style="color:#668866;"&gt;-- Presentando resultados (opcional)&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;Mediante el uso de &amp;eacute;sta t&amp;eacute;cnica podemos aumentar notablemente la velocidad de nuestra consultas y procedimientos almacenados&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=195888" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Optimización de Consultas Parte 3 - Recompilación de procedimientos Almacenados</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/01/17/code-optimizaci-243-n-de-consultas-parte-2-recompilaci-243-n-de-procedimientos-almacenados.aspx" /><id>/blogs/fangarita/archive/2011/01/17/code-optimizaci-243-n-de-consultas-parte-2-recompilaci-243-n-de-procedimientos-almacenados.aspx</id><published>2011-01-17T23:08:00Z</published><updated>2011-01-17T23:08:00Z</updated><content type="html">&lt;p&gt;Cada vez que se ejecuta un procedimiento almacenado en SqlServer por primera vez, se optimiza y su plan de ejecuci&amp;oacute;n se compila y se almacena en el cach&amp;eacute; de SqlServer. Cada&amp;nbsp; vez que el procedimiento almacenado se ejecuta luego de ser almacenado en el cach&amp;eacute;, usar&amp;aacute; el mismo plan de ejecuci&amp;oacute;n, eliminando la necesidad de compilar y de almacenar el plan de ejecuci&amp;oacute;n de dicho procedimiento cada vez que se ejecuta. Si &amp;eacute;ste procedimiento se ejecuta 1000 o m&amp;aacute;s veces por d&amp;iacute;a, los recursos de hardware se optimizan al ahorrarse dichos pasos.&lt;br /&gt;&lt;br /&gt;Si los par&amp;aacute;metros dentro del procedimiento almacenado son id&amp;eacute;nticos en el Where, entonces reusar el plan de ejecuci&amp;oacute;n tiene mucho sentido. Pero qu&amp;eacute; pasa si los valores de los par&amp;aacute;metros en cada ejecuci&amp;oacute;n cambian?, que pasa si el tama&amp;ntilde;o del resultado varia notablemente (Columnas y Filas), que sucede si para unos par&amp;aacute;metros la b&amp;uacute;squeda &amp;oacute;ptima es una b&amp;uacute;squeda por &amp;iacute;ndice, pero para otros valores el mejor camino es un table scan?&lt;br /&gt;&lt;br /&gt;Todo eso depende de que tan gen&amp;eacute;ricos sean los par&amp;aacute;metros, de que tan bien est&amp;eacute; definida la funcionalidad del procedimiento almacenado si est&amp;aacute;n definidos de tal manera que no recarguemos su funcionalidad y que los resultados sean parecidos aun los valores de los par&amp;aacute;metros sean diferentes el procedimiento ejecutar&amp;aacute; de manera &amp;oacute;ptima y obtendr&amp;aacute; todos los beneficios mencionados anteriormente. Pero para el caso contrario, reutilizar el plan de ejecuci&amp;oacute;n puede no ser lo &amp;oacute;ptimo, como resultado la consulta se ejecutar&amp;aacute; m&amp;aacute;s lentamente que si se creara din&amp;aacute;micamente su plan de ejecuci&amp;oacute;n.&lt;br /&gt;&lt;br /&gt;En la mayor&amp;iacute;a de los casos, no es una cuesti&amp;oacute;n de la cual preocuparse, pero si se hace la pregunta, por qu&amp;eacute; mi procedimiento almacenado ejecuta bien en el dise&amp;ntilde;ador de consultas pero toma mucho tiempo en producci&amp;oacute;n, &amp;eacute;ste puede ser el caso. Siempre teniendo en cuenta que el dise&amp;ntilde;o del procedimiento almacenado, junto con granularidad, ofrecen la mejor estrategia para dise&amp;ntilde;arlos y claro para mantenerlos&lt;br /&gt;&lt;br /&gt;C&amp;oacute;mo solucionar el problema:&lt;br /&gt;&lt;br /&gt;1. Aplicar &lt;a title="Recompilaci&amp;oacute;n" href="http://msdn.microsoft.com/es-es/library/ms190439.aspx"&gt;recompilaci&amp;oacute;n &lt;/a&gt;a todos los procedimientos peri&amp;oacute;dicamente&lt;br /&gt;Ejecutar con el procedimiento almacenado del sistema &lt;a title="sp_recompile" href="http://msdn.microsoft.com/en-us/library/aa238892%28v=sql.80%29.aspx"&gt;sp_recompile&lt;/a&gt; sobre todos los procedimientos almacenados de la base de datos (Cada dos o tres meses)&lt;br /&gt;&lt;br /&gt;2. Crear los procedimientos almacenados que consideremos que sean candidatos para sufrir este problema con la opci&amp;oacute;n With Recompile, teniendo en cuenta que cada vez que ejecutemos el procedimiento almacenado el mismo se recompilar&amp;aacute; (se generar&amp;aacute; un nuevo plan de ejecuci&amp;oacute;n)&lt;br /&gt;CREATE PROCEDURE MiProcedimiento&lt;br /&gt;WITH RECOMPILE&lt;br /&gt;AS&lt;br /&gt;....&lt;br /&gt;&lt;br /&gt;3. Si el caso en donde los resultados cambian demasiado dependiendo de valores espec&amp;iacute;ficos y plenamente identificados podemos ejecutarlo usando la opci&amp;oacute;n with recopile de exec: &lt;br /&gt;EXECUTE MiProcedimiento @p2 = &amp;#39;A&amp;#39; WITH RECOMPILE;&lt;br /&gt;GO&lt;br /&gt;&lt;br /&gt;4. Query Hint RECOMPILE&lt;br /&gt;A partir de SqlServer 2005 se introdujo RECOMPILE como query hint, lo que logra este hint es que el analizador de consulta descarte cualquier plan de ejecuci&amp;oacute;n previamente generado para esa consulta dentro del procedimiento almacenado y recompile s&amp;oacute;lo esta consulta&lt;br /&gt;&lt;br /&gt;5. Creando &lt;a title="Gu&amp;iacute;as de Plan" href="http://msdn.microsoft.com/es-es/library/ms190417.aspx"&gt;Gu&amp;iacute;as de Plan de Ejecuci&amp;oacute;n&lt;/a&gt;&lt;br /&gt;Permite realizar cambios administrativos sobre procedimientos almacenados que ya han sido creados en la base de datos que no se puede o no se quiere modificar para agregar alg&amp;uacute;n tipo de optimizaci&amp;oacute;n como la mencionada. Esto se logra forzando hints sobre las consultas o fijando un plan de ejecuci&amp;oacute;n diferente a dicho procedimiento o consulta.&lt;br /&gt;&lt;br /&gt;La creaci&amp;oacute;n de gu&amp;iacute;as de plan es una opci&amp;oacute;n avanzada de administraci&amp;oacute;n es recomendado leer detenidamente la documentaci&amp;oacute;n sobre el tema y luego observar los casos en donde sea prudente aplicarlo&lt;br /&gt;Debemos usar &amp;eacute;ste tipo de soluci&amp;oacute;n cautelosamente dado que usar recompile, aunque nos aseguramos que cada vez el plan de ejecuci&amp;oacute;n generado es correcto, hace que perdamos los muy buenos beneficios de tener un plan de ejecuci&amp;oacute;n almacenado para el procedimiento y nos gu&amp;iacute;a hacia un mejor dise&amp;ntilde;o de los procedimientos almacenados que incluiremos en nuestros sistemas&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=187495" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Info] Optimización de Consultas Parte 1 - Generalidades</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/01/17/info-optimizaci-243-n-de-consultas-parte-1-generalidades.aspx" /><id>/blogs/fangarita/archive/2011/01/17/info-optimizaci-243-n-de-consultas-parte-1-generalidades.aspx</id><published>2011-01-17T15:54:00Z</published><updated>2011-01-17T15:54:00Z</updated><content type="html">&lt;p&gt;En la siguientegr&amp;aacute;fica se presenta el esquema de ejecuci&amp;oacute;n de consultas en SqlServer&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Ejecuci_F300_n-Consultas.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Ejecuci_F300_n-Consultas.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;From y Join&lt;/b&gt;&lt;br /&gt;1. Usar Hints &lt;br /&gt;Podemos utilizar hints de consultas tales como (nolock) sobre las tablas que queremos consultar para cambiar el modo de acceso de readcommited a &lt;a target="_blank" title="readuncommited" href="http://msdn.microsoft.com/es-co/library/ms187373.aspx"&gt;readuncommited &lt;/a&gt;--ADVERTENCIA: Utilizar este hint puede traer problemas de datos, tales como lecturas sucias o registros fantasma.&lt;/p&gt;
&lt;p&gt;El uso de hints debe realizarse con especial cuidado y teniendo en mente las consecuencias de los mismos, asimismo, el optimizador de consultas podr&amp;aacute; f&amp;aacute;cilmente encontrar el mejor camino para retornar la consulta dado que utiliza informaci&amp;oacute;n estad&amp;iacute;stica, cach&amp;eacute;, entre otros elementos para devolver los resultados.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. Otra t&amp;eacute;cnica que podemos usar antes del Where es poner las condiciones del where (cuando sean aplicables) dentro del mismo Join, es decir: &lt;br /&gt;&lt;i&gt;select a.Id, from tabla1 a inner join tabla2 b on a.id = b.id where b.cantidad &amp;gt; 50 &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;puede ser reescrito como:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;select a.Id, from tabla1 a inner join tabla2 b on a.id = b.id and b.cantidad &amp;gt; 50 &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Esto aplica especialmente para sqlServer 2005 y versiones anteriores, el analizador de SqlServer 2008 se vale de su algoritmia avanzada para determinar cu&amp;aacute;l es el mejor camino entre estas dos opciones.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3. Favorecer la l&amp;oacute;gica y operaciones por Conjuntos&lt;br /&gt;Las operaciones por conjuntos implican la realizaci&amp;oacute;n de operaciones por bloques, para lo cual Sql est&amp;aacute; optimizado:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;3.1.&amp;nbsp; Evitar el uso de funciones escalares en las consultas para cada campo (en cualquier parte de la consulta), dado que la ejecuci&amp;oacute;n se realiza una por una, lo cual no favorece las operaciones por bloques.&lt;br /&gt;3.2. Evitar al MAXIMO el uso de cursores.&lt;br /&gt;3.3. Estimular el uso de funciones de usuario que devuelven tablas, pues se calculan primero y luego se aplican a la consulta favoreciendo operaciones de conjuntos.&lt;br /&gt;3.4. Asimismo, estimular el uso de expresiones CTE:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;Permite la reutilizaci&amp;oacute;n de consultas, usando el join, de esta manera consultamos dos (2) veces la misma tabla&lt;br /&gt;&lt;i&gt;select a.Id from tabla1 ainner join tabla2 b on a.Tipo = B.IdTIpo &lt;br /&gt;inner join tabla2 c on a.Tipo2 = C.IdTIpo&lt;/i&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;con CTE, solo una vez:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;i&gt;declare @tabla1 table (Id int, TipoA int, TipoB int) --Solo por ejemplo&lt;br /&gt;declare @tabla2 table (IdTipo int) --Solo por ejemplo&lt;br /&gt;;with Tabla(Id)&lt;br /&gt;as(&lt;br /&gt;select IdTipo from @tabla2&lt;br /&gt;)&lt;br /&gt;select * from @tabla1 a inner join Tabla &lt;br /&gt;on a.TipoA = tabla.id&lt;br /&gt;inner join @tabla1 b on b.TipoB = tabla.id&lt;/i&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Where&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;1. Escribir las expresiones l&amp;oacute;gicas de menos completa a m&amp;aacute;s compleja, es decir, es mejor:&lt;br /&gt;&lt;i&gt;select a.Id, from tabla1 a inner join tabla2 b on a.id = b.id and b.cantidad &amp;gt; 50 and nombre like &amp;#39;%abc%&amp;#39; &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;que usar:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;select a.Id, from tabla1 a inner join tabla2 b on a.id = b.id a nombre like &amp;#39;%abc%&amp;#39; and b.cantidad &amp;gt; 50 &lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Esto se debe a la evaluaci&amp;oacute;n de la l&amp;oacute;gica tipo &lt;a target="_blank" title="Corto Circuito (Ingl&amp;eacute;s)" href="http://en.wikipedia.org/wiki/Short-circuit_evaluation"&gt;corto circuito&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Select &lt;/b&gt;&lt;br /&gt;1. Evitar el uso de funciones escalares por cada campo.&lt;br /&gt;2. Usar Case puede ser una buena alternativa para devolver resultados directamente al usuario, usarlos con precauci&amp;oacute;n, si es posible, reemplazarlos con case del lado del cliente (Reporting Services, por ejemplo).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Order By&lt;/b&gt;&lt;br /&gt;1. Evitar al M&amp;Aacute;XIMO los ordenamientos innecesarios dentro de las consultas, si se observan los planes de ejecuci&amp;oacute;n de las consultas se encuentra que es una de las cosas que m&amp;aacute;s consume buena parte del tiempo de ejecuci&amp;oacute;n de la consulta; se recomienda ordenar, en la mayor&amp;iacute;a de los casos, del lado del cliente.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Result Set&lt;/b&gt;&lt;br /&gt;1. Evitar al M&amp;Aacute;XIMO el uso del &lt;i&gt;select *&lt;/i&gt;, limitar la cardinalidad del resultado (tiene como resultado) permite, genera, mejora el uso de...? mejoras en el uso de memoria y latencia de red, dado que los resultados son s&amp;oacute;lo aquellos que necesitamos, a la vez que evitamos que el analizador de consultas deba determinar din&amp;aacute;micamente qu&amp;eacute; campos usar en el conjunto de resultados.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Grouping and Aggregation&lt;/b&gt;&lt;br /&gt;Una vez finalizada la etapa de la consulta en donde se obtienen los resultados iniciales, el motor procede a realizar el agrupamiento y agregaci&amp;oacute;n de los resultados (agregaci&amp;oacute;n: aplicar una funci&amp;oacute;n a un grupo)&lt;br /&gt;Debemos evitar al m&amp;aacute;ximo realizar Agrupaciones y Agregaciones del lado de la base de datos, dado que son operaciones costosas, esto es especialmente cierto para operaciones de reportes.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Having&lt;/b&gt;&lt;br /&gt;S&amp;oacute;lo debe ser aplicado para filtrar sobre las funciones de agregaci&amp;oacute;n, NO debe ser utilizado para filtrar las filas de la consulta, lo cual se debe incluir en el Where de la consulta. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;OTRAS RECOMENDACIONES&lt;br /&gt;&lt;/b&gt;&lt;a target="_blank" title="CLR" href="http://geeks.ms/blogs/fangarita/archive/2010/08/09/presentaci-243-n-sqlserver-clr.aspx"&gt;Usar CLR&lt;/a&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;Programaci&amp;oacute;n .Net para para crear procedimientos almacenados, funciones de usuario y agregaciones, etc. Usarlo cuando se requiera realizar c&amp;aacute;lculos avanzados del lado de la base de datos, en ning&amp;uacute;n momento debe usarse como reemplazo para las operaciones a acceso a datos.&lt;br /&gt;&lt;br /&gt;Particionamiento de Datos&lt;br /&gt;Crear grupos de archivos en diferentes discos y ubicar en ellos las tablas de mayor uso, lo cual favorece las operaciones INNER JOIN&amp;nbsp; (Versi&amp;oacute;n inferior a la enterprise)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Particionamiento de Vertical de Filas&lt;br /&gt;Crear particionamiento de filas usando funciones de particionamiento para ubicar asimismo las filas en diferentes grupos de archivos y optimizar el acceso a los datos en las operaciones JOIN (versi&amp;oacute;n Enterprise)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dividir las consultas en consultas m&amp;aacute;s peque&amp;ntilde;as&lt;br /&gt;Usando variables tipo tabla podemos realizar consultas preliminares sobre algunas de las tablas que participan en las operaciones JOIN o LEFT JOIN, de esta manera cargaremos a memoria (luego de cierto l&amp;iacute;mite de filas las variables tipo tabla tambi&amp;eacute;n pasan a disco, por lo que debemos ubicar en ellas solo las tablas que relativamente tengan pocos registros: menos de 100,000)&amp;nbsp; de manera anticipada, permiti&amp;eacute;ndonos la reutilizaci&amp;oacute;n de las mismas, con la ventaja que cuando salen de &amp;aacute;mbito se destruyen autom&amp;aacute;ticamente (no hay que realizar un drop como a las tablas temporales). &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;En pr&amp;oacute;ximos art&amp;iacute;culos extender&amp;eacute; estos y otros temas&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDY LEANDRO ANGARITA CASTELLANOS&lt;br /&gt;Sql Server MVP&lt;br /&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=187467" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Optimización de Consultas Parte 2 - Anti Semi joins</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/01/17/code-optimizaci-243-n-de-consultas-parte-i-anti-semi-joins.aspx" /><id>/blogs/fangarita/archive/2011/01/17/code-optimizaci-243-n-de-consultas-parte-i-anti-semi-joins.aspx</id><published>2011-01-17T15:13:00Z</published><updated>2011-01-17T15:13:00Z</updated><content type="html">&lt;p&gt;Como todos los temas de optimizaci&amp;oacute;n las soluciones presentadas en &amp;eacute;ste art&amp;iacute;culo deben probarse, 
intentar varias alternativas y luego decidir dependiendo de los 
resultados y especialmente de la evoluci&amp;oacute;n de los datos, es decir, dependiendo del
 momento del ciclo de vida de la base de datos tendremos cierto uso de 
la informaci&amp;oacute;n (por ejemplo durante procesos de migraci&amp;oacute;n) y luego 
tendremos otro tipo (en Producci&amp;oacute;n, cuando cierto tipo de producto salga
 de circulaci&amp;oacute;n, etc.)&lt;/p&gt;
&lt;p&gt;El proceso de optimizaci&amp;oacute;n y mantenimiento es algo continuo y 
debe estar acorde a las necesidades y cambios del negocio&lt;/p&gt;
&lt;p&gt;Pimero, qu&amp;eacute; es un &lt;b&gt;SEMI JOIN&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Semi-Join.png"&gt;&lt;/a&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Semi-Join.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Semi-Join.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HumanResources.Employee.BusinessEntityID, MyEmployees.EmployeeID&lt;br /&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HumanResources.Employee LEFT OUTER JOIN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyEmployees ON HumanResources.Employee.BusinessEntityID = MyEmployees.EmployeeID&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Es cuando queremos hacer un left (o Right join) con otra(s) tabla(s) y queremos ver qu&amp;eacute; registros figuran en la primera tabla (HumanResources.Employee) y cuales en la segunda(MyEmployees)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Si en la segunda tabla no existe dicho registro se presentar&amp;aacute; NULL como se v&amp;eacute; en la gr&amp;aacute;fica&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ahora, Definamos un &lt;b&gt;ANTI SEMI JOIN&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Anti-Semi-Join.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x437/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Anti-Semi-Join.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HumanResources.Employee.BusinessEntityID, MyEmployees.EmployeeID&lt;br /&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HumanResources.Employee LEFT OUTER JOIN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyEmployees ON HumanResources.Employee.BusinessEntityID = MyEmployees.EmployeeID&lt;br /&gt;WHERE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (MyEmployees.EmployeeID IS NULL)&lt;/p&gt;
&lt;p&gt;Queremos encontrar los registros que est&amp;eacute;n en la primera tabla (HumanResources.Employee) que NO&amp;nbsp; est&amp;eacute;n en la segunda tabla (MyEmployee)&lt;/p&gt;
&lt;p&gt;&amp;Eacute;sta consulta cumple su cometido pero analicemos a fondo su funcionamiento, realiza el Left Join que mas pesado que realizar un inner join normal y filtra los resultados para la columna null&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ahora, qu&amp;eacute; &lt;b&gt;ALTERNATIVA &lt;/b&gt;tenemos para &amp;eacute;ste caso:&lt;/p&gt;
&lt;p&gt;Usaremos la funci&amp;oacute;n &lt;a target="_blank" title="Exists" href="http://technet.microsoft.com/es-es/library/ms188336.aspx"&gt;Exists&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SELECT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a.BusinessEntityID&lt;br /&gt;FROM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HumanResources.Employee a&lt;br /&gt;where not exists(select EmployeeID from MyEmployees b where a.BusinessEntityID = b.EmployeeID)&lt;/p&gt;
&lt;p&gt;Observemos la comparaci&amp;oacute;n entre el primer m&amp;eacute;todo y la alternativa:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Comparacion.png"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/Comparacion.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El costo relativo para el batch es el mismo, y aparentemente tienen&amp;nbsp; el mismo costo, pero observemos 2 cosas interesantes sobre &amp;eacute;ste plan de ejecuci&amp;oacute;n, primero es que de la primera manera tenemos un filtro, es de recordar que los ordenamientos, las agrupaciones y los filtros son las operaciones m&amp;aacute;s costosas dentro de una consulta; en la segunda parte ejecutando con Not Exists, vemos que el analizador identifica que es un Left Anti Semi Join, por lo cual autom&amp;aacute;ticamente aplica las optimizaciones para este caso y luego realiza las operaciones adicionales de la consulta&lt;/p&gt;
&lt;p&gt;Usando repetidamente &amp;eacute;sta t&amp;eacute;cnica, especialmente para consultas que impliquen muchos registros puede aumentar el rendimiento de la misma a la vez que permite una facil escritura y mantenimiento e incluso control sobre la consulta a realizar&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDDY LEANDRO ANGARITA CASTELLANOS&lt;/b&gt; &lt;br /&gt;Sql Server MVP&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://geeks.ms/controlpanel/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;/a&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=187460" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Crear una tabla a partir de un texto separado por comas (CSV)</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2011/01/03/code-crear-una-tabla-a-apartir-de-un-texto-se.aspx" /><id>/blogs/fangarita/archive/2011/01/03/code-crear-una-tabla-a-apartir-de-un-texto-se.aspx</id><published>2011-01-03T22:24:00Z</published><updated>2011-01-03T22:24:00Z</updated><content type="html">&lt;p&gt;Ahora con la aparici&amp;oacute;n de los par&amp;aacute;metros tipo tabla en SqlServer, se elimina la necesidad de crear parametros complejos o de trucos para enviar informaci&amp;oacute;n hacia los procedimientos almacenados, pero para quienes no quieren enviar esta informaci&amp;oacute;n, crear los tipos de datos que se requieren para recibir los par&amp;aacute;metros tipo tabla, presento una alternativa para ello en varias aproximaciones&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Funci&amp;oacute;n de usuario para la generaci&amp;oacute;n de Tablas&lt;/b&gt;&lt;/p&gt;
&lt;pre&gt;--USO: select * from fnCSV2Table(&amp;#39;1,2,3,4,5,6,7,8&amp;#39;,default)&lt;br /&gt;--Convierte una CSV a una tabla, lo que facilita las consultas &lt;br /&gt;--Reduce la necesidad de consultas din&amp;aacute;micas dentro de los procedimientos almacenados&lt;br /&gt;create function fnCSV2Table(@CSV varchar(max), @Separator char(1) = &amp;#39;,&amp;#39;)&lt;br /&gt;returns @list table (data int)&lt;br /&gt;as&lt;br /&gt;Begin&lt;br /&gt;	declare @SecondIndex int&lt;br /&gt;	declare @FirtsIndex int&lt;br /&gt;	&lt;br /&gt;	set @SecondIndex = charindex(@Separator,@CSV)&lt;br /&gt;	set @FirtsIndex = 0&lt;br /&gt;	&lt;br /&gt;	if @SecondIndex &amp;gt; 0 set @CSV = @CSV + @Separator&lt;br /&gt;	&lt;br /&gt;	while (@SecondIndex &amp;gt; 0)&lt;br /&gt;	Begin&lt;br /&gt;		insert into @list values(substring(@CSV,@FirtsIndex,@SecondIndex - @FirtsIndex))&lt;br /&gt;		set @FirtsIndex = @SecondIndex + 1&lt;br /&gt;		set @SecondIndex = charindex(@Separator,@CSV,@FirtsIndex)&lt;br /&gt;	End&lt;br /&gt;	if @FirtsIndex =0 and len(@CSV)&amp;gt;0 &lt;br /&gt;		insert into @list values(@CSV)&lt;br /&gt;	return&lt;br /&gt;End&lt;br /&gt;go&lt;br /&gt;&lt;br /&gt;--USO: select * from fnConvertCSV2TextTable(&amp;#39;1,2,3,4,5,6,7,8&amp;#39;,default)&lt;br /&gt;--Convierte una CSV a una tabla (tipo texto), lo que facilita las consultas &lt;br /&gt;--Reduce la necesidad de consultas din&amp;aacute;micas dentro de los procedimientos almacenados&lt;br /&gt;create function fnConvertCSV2TextTable(@CSV varchar(max), @Separator char(1) = &amp;#39;,&amp;#39;)&lt;br /&gt;returns @list table (data varchar(8000))&lt;br /&gt;with encryption&lt;br /&gt;as&lt;br /&gt;Begin&lt;br /&gt;	declare @SecondIndex int&lt;br /&gt;	declare @FirtsIndex int&lt;br /&gt;	&lt;br /&gt;	set @SecondIndex = charindex(@Separator,@CSV)&lt;br /&gt;	set @FirtsIndex = 0&lt;br /&gt;	&lt;br /&gt;	if @SecondIndex &amp;gt; 0 set @CSV = @CSV + @Separator&lt;br /&gt;	&lt;br /&gt;	while (@SecondIndex &amp;gt; 0)&lt;br /&gt;	Begin&lt;br /&gt;		insert into @list values(substring(@CSV,@FirtsIndex,@SecondIndex - @FirtsIndex))&lt;br /&gt;		set @FirtsIndex = @SecondIndex + 1&lt;br /&gt;		set @SecondIndex = charindex(@Separator,@CSV,@FirtsIndex)&lt;br /&gt;	End	&lt;br /&gt;	if @FirtsIndex =0 and len(@CSV)&amp;gt;0 &lt;br /&gt;		insert into @list values(@CSV)&lt;br /&gt;	return&lt;br /&gt;End&lt;br /&gt;go&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;Es posible que no sea la aproximaci&amp;oacute;n mas &amp;oacute;ptimizada desde el punto de vista programaci&amp;oacute;n T-Sql, pero si es seguro, soluciona el problema de una manera simple y facil de administrar&lt;/p&gt;
&lt;p&gt;&lt;b&gt;C&amp;oacute;mo Usuarla&lt;/b&gt; &lt;/p&gt;
&lt;p&gt;Una vez convertida a tabla podemos usarla en un join para filtrar los datos que queremos consultar, podemos usar Cross Apply para aplicar a cada registro la funci&amp;oacute;n, etc., la idea es generar una tabla y poderla utilizar facilmente dentro de nuestro c&amp;oacute;digo&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDDY LEANDRO ANGARITA CASTELLANOS&lt;/b&gt; &lt;br /&gt;Sql Server MVP&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=186722" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Cómo generar N Filas Rápido Sql Server</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2010/12/22/code-c-243-mo-generar-n-filas-r-225-pido-sql-server.aspx" /><id>/blogs/fangarita/archive/2010/12/22/code-c-243-mo-generar-n-filas-r-225-pido-sql-server.aspx</id><published>2010-12-22T14:35:00Z</published><updated>2010-12-22T14:35:00Z</updated><content type="html">&lt;p&gt;Como siempre, una de las cosas que mas se necesita al crear un procedimiento es generar un n&amp;uacute;mero de determinado de filas para poderlas combinar con alguna otra tabla, &amp;eacute;sta t&amp;eacute;cnica presenta c&amp;oacute;mo crear una tabla que cuente de un n&amp;uacute;mero a otro, en incrementos de m&amp;aacute;nera eficiente&lt;/p&gt;
&lt;p&gt;&lt;b&gt;LA PRIMERA APROXIMACI&amp;Oacute;N&lt;/b&gt;&lt;/p&gt;
&lt;pre&gt;declare @StartNumber int, @Nrows int, @increment int&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;set @StartNumber = 1&lt;br /&gt;set @Nrows  = 1000000&lt;br /&gt;set @increment = 1&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;----&lt;br /&gt;declare @q table  (i int)&lt;br /&gt;declare @index int&lt;br /&gt;&lt;br /&gt;set @index = @StartNumber &lt;br /&gt;&lt;br /&gt;while @index &amp;lt; @Nrows &lt;br /&gt;Begin&lt;br /&gt;	insert into @q values(@index)&lt;br /&gt;	set @index = @index + @increment &lt;br /&gt;End&lt;br /&gt;&lt;br /&gt;select i from @q &lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;En &amp;eacute;ste punto, se genera el resultado y tiene los par&amp;aacute;metros que se podr&amp;iacute;an esperar: el Inicio, El n&amp;uacute;mero de filas y el Incremento, pero al ejecutarlo con un mill&amp;oacute;n de filas, toma (en mi computador) 25 segundos, lo cual es muy lento, sin emabrgo &amp;eacute;sta aproximaci&amp;oacute;n tendr&amp;iacute;aa el l&amp;iacute;mite de registros del tipo de datos que usemos como par&amp;aacute;metro, es decir, se puede llegar hasta el m&amp;aacute;ximo que permite un entero, o el m&amp;aacute;ximo que soporte un bigint, lo cual es bastante grande, pero mucho mas lento al hacerlo uno por uno. Ahora vamos a investigar otra alternativa que nos permitir&amp;aacute; generar los registros mucho m&amp;aacute;s r&amp;aacute;pido usando otras t&amp;eacute;cnicas&lt;/p&gt;
&lt;p&gt;&lt;b&gt;SEGUNDA APROXIMACI&amp;Oacute;N&lt;/b&gt;&lt;/p&gt;
&lt;pre&gt;declare @StartNumber int, @NumberOfRows int, @Increment int&lt;br /&gt;&lt;br /&gt;set @StartNumber = 1&lt;br /&gt;set @NumberOfRows = 1000000&lt;br /&gt;set @Increment = 1&lt;br /&gt;&lt;br /&gt;declare @Rows table (i int)&lt;br /&gt;&lt;br /&gt;Declare @NumGen Table (Num int)	&lt;br /&gt;Declare @cnt int	&lt;br /&gt;Set @cnt = @StartNumber&lt;br /&gt;While @cnt &amp;lt;= 100 &lt;br /&gt;Begin		&lt;br /&gt;	Insert Into @NumGen values (@cnt)&lt;br /&gt;	Set @cnt = @cnt + @Increment&lt;br /&gt;End	&lt;br /&gt;set @StartNumber = @StartNumber - @Increment &lt;br /&gt;&lt;br /&gt;insert into @Rows&lt;br /&gt;Select @StartNumber + RowNum	From 	&lt;br /&gt;(&lt;br /&gt;Select Row_Number() Over (Order By N1.Num) As RowNum&lt;br /&gt;From @NumGen N1, @NumGen N2, @NumGen N3, @NumGen N4, @NumGen N5, @NumGen N6, @NumGen N7, @NumGen N8, @NumGen N9, @NumGen N10) RowNums	&lt;br /&gt;Where RowNum &amp;lt;= @NumberOfRows&lt;br /&gt;&lt;br /&gt;select * from @Rows&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Lo que sucede es que estamos haciendo una generaci&amp;oacute;n inicial de una tabla hasta 100 normalmente (tambi&amp;eacute;n porque para casos en donde la tabla a generar es mas corta) y luego multiplicando por conjuntos &amp;eacute;ste esfuerzo con el fin de no generar una a una las filas sino por bloques de a 100 filas y en &amp;eacute;ste caso 10 bloques de a 100 filas, al hacer &amp;eacute;sta combinaci&amp;oacute;n aplicamos una combinaci&amp;oacute;n lo cual nos da un m&amp;aacute;ximo de filas a generar de 100^10, lo cual suficiente en la mayor&amp;iacute;a de los casos. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Usando nuestra soluci&amp;oacute;n podemos generar la funci&amp;oacute;n con la firma: &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre&gt;alter function GenTable(@StartNumber int, @NumberOfRows int, @Increment int = 1)&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Y podemos utilizarlo para crear un ejemplo: Imaginemos que queremos agregar hora a hora las siguientes 12 horas a las fechas de actividad de un cliente, c&amp;oacute;mo se podr&amp;iacute;a hacer? &lt;/p&gt;
&lt;p&gt;&lt;b&gt;EJEMPLO DE USO&lt;/b&gt;&lt;/p&gt;
&lt;pre&gt;--Tabla que proviene de la Base de Datos simulada--&lt;br /&gt;declare @fechas table (IdCliente int, Fecha datetime)&lt;br /&gt;&lt;br /&gt;insert into @fechas values &lt;br /&gt;(1, &amp;#39;2001-01-20 08:23:20&amp;#39;), &lt;br /&gt;(2, &amp;#39;2001-02-24 18:23:20&amp;#39;), &lt;br /&gt;(3, &amp;#39;2001-03-23 12:23:20&amp;#39;)&lt;br /&gt;--Fin Tabla que proviene de la Base de Datos simulada--&lt;br /&gt;&lt;br /&gt;select * from @fechas &lt;br /&gt;&lt;br /&gt;insert into @fechas &lt;br /&gt;select IdCliente, DATEADD(hh,ids.i,fecha) as FechasHoras  from @fechas &lt;br /&gt;cross join (select i from dbo.GenTable(1,12,default)) Ids&lt;br /&gt;order by FechasHoras&lt;br /&gt;&lt;br /&gt;select * from @fechas &lt;br /&gt;order by Fecha &lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Aplicamos cada registro generado a cada una de las filas (CrossJoin) que provienen de la tabla y luego usamos la funci&amp;oacute;n DateAdd para hacer el trabajo fila a fila, sin usar cursores, sin necesidad de recorrer la variable tipo tabla y como siempre favoreciendo las operacione de conjunto sobre las operaciones realizadas fila a fila &lt;/p&gt;
&lt;p&gt;&amp;nbsp;Por supuesto exiiten otras alternattivas se puede generar usando CTE, la cuesti&amp;oacute;n es la bandera MAXRECURSION, la cual limita el rango de acci&amp;oacute;n de la soluci&amp;oacute;n planteada a cierto n&amp;uacute;mero de registos (depende de la implementaci&amp;oacute;n) Y claro la MAS recomendada y eficiente de todas que es usar CLR, especial para este tipo de casos Los invito a probar las diferentes alternativas y enviar sus comentarios sobre el tema &lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDDY LEANDRO ANGARITA CASTELLANOS&lt;/b&gt; &lt;br /&gt;Sql Server MVP&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=186262" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry><entry><title>[Code] Cómo calcular un total acumulado Rápido SIN Cursores</title><link rel="alternate" type="text/html" href="/blogs/fangarita/archive/2010/10/28/code-c-243-mo-calcular-un-total-acumulado-r-225-pido-sin-cursores.aspx" /><id>/blogs/fangarita/archive/2010/10/28/code-c-243-mo-calcular-un-total-acumulado-r-225-pido-sin-cursores.aspx</id><published>2010-10-28T20:36:00Z</published><updated>2010-10-28T20:36:00Z</updated><content type="html">&lt;p&gt;Una de las cosas que nos lleva a usar cursores es el c&amp;aacute;lculo de totales acumulados, as&amp;iacute; que usando una de las carater&amp;iacute;sticas no muy documentadas de SQL podemos realizar &amp;eacute;ste trabajo con poco esfuerzo y de una manera r&amp;aacute;pida y efectiva &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;--DBCC DROPCLEANBUFFERS -- Limpia cach&amp;eacute; de datos&lt;/b&gt; SOLO SE UTILIZA PARA COMPARAR CON OTRAS IMPLEMENTACIONES ELIMNAR EN AMBIENTE DE PRODUCCI&amp;Oacute;N&lt;/p&gt;
&lt;p&gt;&lt;b&gt;--DBCC FREEPROCCACHE -- Limipia el cach&amp;eacute; de procedimientos&lt;/b&gt; SOLO SE UTILIZA PARA COMPARAR CON OTRAS IMPLEMENTACIONES ELIMNAR EN AMBIENTE DE PRODUCCI&amp;Oacute;N&lt;/p&gt;
&lt;p&gt;&lt;b&gt;GO &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;declare @runningtotal decimal(17,2) &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;set @runningtotal = 0 &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;update TablaValores &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;set @runningtotal = ValorAcumulado = @runningtotal + ValorFila &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Espero sea de ayuda &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;FREDDY LEANDRO ANGARITA CASTELLANOS&lt;/b&gt; &lt;br /&gt;Sql Server MVP&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/fangarita/MVPLogo.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=184079" width="1" height="1"&gt;</content><author><name>fangarita</name><uri>http://geeks.ms/members/fangarita/default.aspx</uri></author></entry></feed>
