segunda-feira, 25 de março de 2013

Postgresql - Paginação com Filtros e Ordenação

Para o caso de precisarmos criar uma consulta que nos retorne os dados paginados com filtros e ordenados
Veja no exemplo abaixo como é facil usando Postgresql

------------------------------------------------------------------
SELECT Z.* FROM 
  (      SELECT  1 AS ID, 'UM'     AS DESCRICAO    ,12 AS NUMERO
   UNION SELECT  2 AS ID, 'DOIS'   AS DESCRICAO    ,15 AS NUMERO   
   UNION SELECT  3 AS ID, 'TRÊS'   AS DESCRICAO    ,26 AS NUMERO   
   UNION SELECT  4 AS ID, 'QUATRO' AS DESCRICAO    ,20 AS NUMERO  
   UNION SELECT  5 AS ID, 'CINCO'  AS DESCRICAO    ,23 AS NUMERO   
   UNION SELECT  6 AS ID, 'SEIS'   AS DESCRICAO    ,32 AS NUMERO   
   UNION SELECT  7 AS ID, 'SETE'   AS DESCRICAO    ,14 AS NUMERO  
   UNION SELECT  8 AS ID, 'OITO'   AS DESCRICAO    ,27 AS NUMERO   
   UNION SELECT  9 AS ID, 'NOVE'   AS DESCRICAO    ,11 AS NUMERO   
   UNION SELECT 10 AS ID, 'DEZ'    AS DESCRICAO    ,21 AS NUMERO   
  ) Z
           WHERE UPPER(Z.DESCRICAO) LIKE UPPER('%%') --filtros diversos
        ORDER BY Z.ID -- Ordenação
           LIMIT 3  -- Quantidade de registros por página
          OFFSET (3 - 1) * 3 
               --(Numero da Pagina -1) * Quantidade registros por página

------------------------------------------------------------------

SQL Server 2000 - Paginação com Filtros e Ordenação

Bom, em se tratando de listagem de dados, algumas vezes encontramos a necessidade de fazer uma query que nos retorne muitos registros, neste momento é hora de pensar em dados paginados, onde é apresentado alguns registros a cada página, mas em muitos casos é necessário deixar disponível a ordenação a cargo do usuário, ao clicar no cabeçalho executa ordenação pela mesma.
Segue abaixo uma solução para criar uma Stored Procedure, que a consulta retorne apenas o que queremos evitando muitos registros ocultos ou depender de componentes externos, além de poder aplicar filtros e ordenação.

-----------------------------------------------------------------------
--Populando uma tabela para o exemplo
-----------------------------------------------------------------------
DECLARE @TABELA TABLE(
                      ID        INT
                     ,DESCRICAO VARCHAR(100)
                     ,NUMERO    INT
                     )
INSERT INTO @TABELA
                          SELECT  1, 'UM'    ,12
                    UNION SELECT  2, 'DOIS'  ,15
                    UNION SELECT  3, 'TRÊS'  ,26
                    UNION SELECT  4, 'QUATRO',20
                    UNION SELECT  5, 'CINCO' ,23
                    UNION SELECT  6, 'SEIS'  ,32
                    UNION SELECT  7, 'SETE'  ,14
                    UNION SELECT  8, 'OITO'  ,27
                    UNION SELECT  9, 'NOVE'  ,11
                    UNION SELECT 10, 'DEZ'   ,21

-----------------------------------------------------------------------
--Parâmetros da StoredProcedure
-----------------------------------------------------------------------
--Filtros
DECLARE @Filtro_ID        INT          --ID EXATO
DECLARE @Filtro_DESCRICAO VARCHAR(100) --PARTE DA DESCRICAO
DECLARE @Filtro_NUMERO    INT          --NUMERO EXATO

--Ordenação
DECLARE @Ordenacao      INT          --ATRAVEZ DO INDICE INFORMADO

--Paginação
DECLARE @NrPagina       INT          --INFORMA O NUMERO DA PÁGINA 
DECLARE @PorPagina      INT          --INFORMA REGISTROS POR PÁGINA
DECLARE @TemProxima     CHAR(1)      --RETORNA 'S' COM PROXIMA PÁGINA 
                                     --     OU 'N' SEM PROXIMA PÁGINA
-----------------------------------------------------------------------
--Valores para exemplificar este seriam os dados de entrada da Procedure
SET @Filtro_ID        = NULL
SET @Filtro_DESCRICAO = NULL
SET @Filtro_NUMERO    = NULL
SET @NrPagina         = 1
SET @PorPagina        = 3
SET @Ordenacao        = NULL
-----------------------------------------------------------------------

DECLARE @IndexInicial INT 
SET @IndexInicial = (@NrPagina * @PorPagina ) - @PorPagina 

--CRIANDO ESTRUTURA IGUAL TABELA MAS COM COLUNA ROWID ORDENADO E FILTRADO
DECLARE @TABELA_PRONTA TABLE(
                               ROWID     INT IDENTITY(1,1)
                              , ID        INT
                              , DESCRICAO VARCHAR(100)
                              , NUMERO INT
                              )

--INSERINDO DADOS PRONTOS PARA SEREM APRESENTADOS
INSERT INTO @TABELA_PRONTA (ID, DESCRICAO, NUMERO)
   SELECT E.ID ,E.DESCRICAO ,E.NUMERO      
     FROM @TABELA E
    WHERE ( E.ID = @ID OR @ID IS NULL )
      AND ( UPPER(E.DESCRICAO) LIKE '%'+UPPER(@DESCRICAO)+'%' 
            OR @DESCRICAO IS NULL )
      AND (E.NUMERO = @NUMERO OR @NUMERO IS NULL)
 ORDER BY CASE --ORDENACOES INTEIRAS
             WHEN @Ordenacao = 1 THEN E.ID
             WHEN @Ordenacao = 3 THEN E.NUMERO
          END,
          CASE --ORDENACOES VARCHAR
             WHEN @Ordenacao = 2 THEN E.DESCRICAO
          END


--PAGINAÇÃO
SET ROWCOUNT @PorPagina

SELECT E.ROWID
      ,E.ID
      ,E.DESCRICAO
      ,E.NUMERO
  FROM @TABELA_PRONTA E
 WHERE ROWID > @IndexInicial

SET ROWCOUNT 0

--Informando se existe próxima página
SELECT @TemProxima = CASE 
                        WHEN COUNT(ID) > (@NrPagina * @PorPagina ) THEN 
                           'S'
                        ELSE 
                           'N'
                     END
  FROM @TABELA

-----------------------------------------------------------------------
Até o próximo post.

sábado, 16 de março de 2013

SQL Server 2000 - Stored Procedure com parâmetro para IN

Em alguns momentos em nossa jornada de trabalho podemos precisar criar uma Stored Procedure no qual precisamos passar como parâmetro de entrada um conjunto de dados (para a clausula IN da Query) com a finalidade de realizar o filtro dos dados. O trecho de código abaixo foi construido para ser executado sem a necessidade de criação de objetos, mantendo a lógica, basta criar a Stored Procedure de acordo com a necessidade e usando as tabelas reais.
Basta copiar, colar e executar.

-----------------------------------------------------------------------
--Criamos uma tabela populada para montar nosso exemplo 
-----------------------------------------------------------------------
DECLARE @TABELA TABLE(ID INT, DESCRICAO VARCHAR(100))
INSERT INTO @TABELA
      SELECT  1, 'UM'       UNION SELECT  2, 'DOIS'     
UNION SELECT  3, 'TRÊS'     UNION SELECT  4, 'QUATRO'   
UNION SELECT  5, 'CINCO'    UNION SELECT  6, 'SEIS'     
UNION SELECT  7, 'SETE'     UNION SELECT  8, 'OITO'     
UNION SELECT  9, 'NOVE'     UNION SELECT 10, 'DEZ'
-----------------------------------------------------------------------

DECLARE @SEPARADOR CHAR(1)           --Parâmetro de Entrada
DECLARE @DADOS     VARCHAR(8000)     --Parâmetro de Entrada

DECLARE @VALOR     VARCHAR(8000)
DECLARE @TABELA_IN TABLE (VALOR VARCHAR(8000))

--Exemplo de dados nos parâmetros de entrada
SET @SEPARADOR = ','
SET @DADOS     = 'UM,TRÊS,CINCO,SETE,NOVE'


SET @DADOS     = @DADOS + @SEPARADOR

--Percorrendo @DADOS para gravar os Itens na tabela temporária buscando
--por meio do @SEPARADOR.
WHILE LEN(@DADOS) > 0
BEGIN
   SET @VALOR = 
        LTRIM(SUBSTRING(@DADOS, 1, CHARINDEX(@SEPARADOR, @DADOS) - 1))
   SET @DADOS = 
        SUBSTRING(@DADOS, CHARINDEX(@SEPARADOR, @DADOS) + 1, LEN(@DADOS))

   INSERT INTO @TABELA_IN (VALOR) VALUES (@VALOR)
END

--Realizando a consulta desejada
SELECT T.ID, T.DESCRICAO
  FROM @TABELA T  
 WHERE T.DESCRICAO IN (SELECT VALOR FROM @TABELA_IN)

-----------------------------------------------------------------------