terça-feira, 18 de outubro de 2011

Consulta CrossTab

Pessoal,


Resolvi postar aqui uma solução para "virar" uma tabela.

Vejo poucas pessoas perguntando a respeito, mas tenho a impressão, por experiência própria, de que as pessoas não imaginam que seja possível resolver esse problema via SQL.


Para os que tiveram alguma experiência com MS Access, saberão exatamente do que estou falando: Consulta de Referência Cruzada. Para os que ainda não entenderam é quando você precisa pegar linhas (dados) de uma tabela e exibí-las em colunas.

O exemplo abaixo faz isso utilizando uma procedure. É bem simples e funciona bem. Obviamente dependendo da quantidade de registros essa leitura pode ficar um tanto lenta.



CREATE PROC [dbo].[sp_CrossTab]
@Table VARCHAR(255),
@RowFld VARCHAR(255),
@ColFld VARCHAR(255),
@ValFld VARCHAR(255),
@Filter VARCHAR(255),
@AggFunct VARCHAR(255)
AS
BEGIN
DECLARE @SQL AS VARCHAR(8000)
DECLARE @CursorSQL AS VARCHAR(8000)
DECLARE @ColVal AS VARCHAR(1024)
DECLARE @NewCol AS VARCHAR(2048)

/* get col hdrs */
SET @CursorSQL = 'DECLARE FldCursor CURSOR FAST_FORWARD FOR '
+ 'SELECT ' + @ColFld + ' FROM ' + @Table + ' GROUP BY '
+ @ColFld + ' ORDER BY ' + @ColFld
EXEC( @CursorSQL )
OPEN FldCursor

/* traverse col hdrs, generating SQL for table */
SET @SQL = 'SELECT ' + @RowFld
FETCH NEXT FROM FldCursor INTO @ColVal
WHILE 0 = @@FETCH_STATUS
BEGIN
SET @NewCol = ', ' + @AggFunct + '(CASE ' + @ColFld + ' WHEN '''
+ @ColVal + ''' THEN ' + @ValFld + ' ELSE NULL END) AS [' + @ColVal + ']'
SET @SQL = @SQL + @NewCol
FETCH NEXT FROM FldCursor INTO @ColVal
END
CLOSE FldCursor
DEALLOCATE FldCursor

/* finish SQL */
SET @SQL = @SQL + ' FROM ' + @Table
IF 0 < LEN( @Filter) SET @SQL = @SQL + ' WHERE ' + @Filter SET @SQL = @SQL + ' GROUP BY ' + @RowFld + ' ORDER BY ' + @RowFld /* run it! */ /* PRINT @SQL */ EXEC( @SQL) END





Nenhum comentário:

Postar um comentário