none
cursor para iniciantes RRS feed

  • Pergunta

  • Olá pessoal, estou treinando um cursor, queria uma ajudinhas de vocês.

    Tenho duas tabelas, tbprincipal e tbhistorico. Nelas tem registros de produtos e valor anual desses produtos. Na minha tabela principal só fica os registro do ano atual e na historico os valores de todos os outros anos.


    um select simples da minha tabela:

    select 
       id_prod,
       produto,
       valor_anual,
       valor/12 as 'valor_mensal',
       ano
    from tb_produto

    obs: Divido o valor anual por 12, pra saber qual o valor minimo que posso pagar por mês;


    Comecei a fazer um cursor pra testar, mas travei. Gostaria que me retornasse os dados da tabela principal e historico, somando os valor por ano. 

    ex:

    PRODUTOS		VALOR_MENSAL     VALOR_ANUAL    ANO
    TECLADOS	        R$ 1.000,00	R$ 12.000,00    2020
    CADEIRAS		R$ 2.000,00	R$ 24.000,00    2020
    MESAS           	R$ 4.000,00	R$ 48.000,00    2020
    NOTEBOOK        	R$ 6.100,00	R$ 73.200,00    2020
    COMPUTADORES    	R$ 10.100,00	R$ 121.200,00   2020
                            R$ 23.200,00	R$ 278.400,00   2020
    TECLADOS	        R$ 1.000,00	R$ 12.000,00    2019
    CADEIRAS  	        R$ 2.000,00	R$ 24.000,00    2019
    MESAS             	R$ 4.000,00	R$ 48.000,00    2019
    NOTEBOOK         	R$ 6.000,00	R$ 72.000,00    2019
    COMPUTADORES     	R$ 10.000,00	R$ 120.000,00   2019
                            R$ 23.000,00	R$ 276.000,00   2019

    obs:as 2 linhas na coluna PRODUTOS em branco, são a somatória anual.

    Fiz um cursor que me trouxesse isso, mas buguei. 

    declare @tb_gasto table(
                            id int identity,
                            produto varchar(50), 
                            valor_anual decimal(15, 2), 
                            valor_mensal decimal(15, 2)
                        )
    
    
    declare 
            @produto varchar(50),
            @valor_anual decimal(15, 2),
            @valor_mensal decimal(15, 2),
            @ano int, 
            @ln int = 1
    
     
    
    declare g_cursor cursor for 
    select * from 
    (
        SELECT
               produto as prod
              ,valor/12 as valor_mensal
              ,valor as valor_anual
              ,ano
        FROM tb_produto
        union all
        SELECT 
               produto as prod
              ,valor/12 as valor_mensal
              ,valor as valor_anual
              ,ano
                  
        FROM tb_produto_historico
    ) as tb where produto != 'Plano Individual'   order by   ano
    
     
    
    open g_cursor
    fetch next from g_cursor into @produto, @valor_mensal, @valor_anual, @ano
    
    WHILE @@FETCH_STATUS = 0 
    begin
        select  @ln, @produto, @valor_mensal, @valor_anual, @ano
    
    
        fetch next from g_cursor into @produto, @valor_mensal, @valor_anual, @ano
    
        set @ln = @ln + 1
    end;
    
    CLOSE g_cursor;  
    DEALLOCATE g_cursor;


    sexta-feira, 31 de janeiro de 2020 20:08

Respostas

Todas as Respostas

  • Deleted
    sexta-feira, 31 de janeiro de 2020 20:47
  • acho que isso te ajuda:

    obs. : se as duas tabelas tem as mesmas colunas pode usar o script abaixo:

    #1

    select * from tb_produtos
    union all
    select * from tb_historico
    order by ano


    sexta-feira, 31 de janeiro de 2020 20:54
  • SS_DBAJr,

    Em outro post que você mesmo iniciou foi dado uma sugestão similar a proposta aqui.

    Veja: https://social.msdn.microsoft.com/Forums/sqlserver/pt-BR/488f9791-e6cf-4706-86ff-2b7a2a8a2499/trigger-eliminando-os-dados-atuais?forum=520


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    sexta-feira, 31 de janeiro de 2020 23:29
  • Deleted
    sábado, 1 de fevereiro de 2020 09:18
  • Oi José, fiz alteração, mas fica carregando e não retorna nada. 

    segunda-feira, 3 de fevereiro de 2020 18:44
  • Oi José, dei uma lida no artigo. 

    Pelo o que entendi, o particionamento, é recomendável, quando se trata de muitos dados. É isso mesmo, ou estou errada?

    Porque se for isso, não é o caso. a Tabela não tende a crescer muito.

    E hoje ja utilizo o UNION. entre a principal e a histórico.

    Peço desculpa desde já, se estou falando besteira.

    segunda-feira, 3 de fevereiro de 2020 19:27
  • Oi José, dei uma lida no artigo. 

    Pelo o que entendi, o particionamento, é recomendável, quando se trata de muitos dados. É isso mesmo, ou estou errada?

    Porque se for isso, não é o caso. a Tabela não tende a crescer muito.

    E hoje ja utilizo o UNION. entre a principal e a histórico.

    Peço desculpa desde já, se estou falando besteira.

    SS_DBAJr,

    Peço licença para responder este seu questionamento, com base, na sua observação: "Pelo o que entendi, o particionamento, é recomendável, quando se trata de muitos dados. É isso mesmo, ou estou errada?"

    Não podemos dizer que esta certa ou errada, existe uma ponto de vista, uma análise e percepção do que pode ser indicado para seu ambiente, pois você conhece o mesmo melhor do que nós.

    O importante a destacar quando se fala sobre visão particionada é que a mesma consiste em uma técnica bem recomendada quando queremos juntar diversas tabelas com a mesma estrutura e dados similares sendo consultados nestas respectivas tabelas, formando um único result set, ou seja, um único resultado.

    Em adicional o uso de visão particionada é muito interessante e viável quando temos em uma única tabela, uma estrutura considerada grande, tanto na horizontal em relação a quantidade de colunas, como também na vertical em relação a quantidade de linhas, o que nos faz analisar a alternativa de estabelecer faixas de dados em nossas pesquisas, no caso criar fatias de dados existentes na mesma tabela, que podem ser estruturados em Selects distintos e processados também desta forma, criando no final um resultado consolidado apresentando a união destes dados, que formam e definem um único result set.

    Para este seu cenário, parece que você analisou e identificou que a Visão Particionada e até mesmo o Cursor não seriam as melhores possibilidades. Estou certo?

    Bom se for isso, talvez uma alternativa mais simples e até mesmo mais fácil de ser desenvolvida e implementada, seria elaborar uma CTE para estabelecer esta somatória ou análise incremental dos dados, bem como, transformar esta sua condição e lógica em uma Stored Procedure!

    O que você acha?


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 3 de fevereiro de 2020 20:05
  • Sim, acho que Stored Procedure seria melhor mesmo. Qeria fazer um cursor, pra saber como seria, por nunca ter usado. E como a tabela não tende a ser volumosa. achei que poderia arriscar nela. Porque sei que ele não é recomendado, para grandes volumes.

    segunda-feira, 3 de fevereiro de 2020 20:19
  • Deleted
    segunda-feira, 3 de fevereiro de 2020 20:28
  • Entendi o que quis dizer, realmente seria melhor.

    Obrigada.

    segunda-feira, 3 de fevereiro de 2020 20:54
  • Deleted
    • Marcado como Resposta SS_DBAJr segunda-feira, 3 de fevereiro de 2020 22:04
    segunda-feira, 3 de fevereiro de 2020 21:29
  • Queria fazer um cursor, pra saber como seria, por nunca ter usado. E como a tabela não tende a ser volumosa. achei que poderia arriscar nela. Porque sei que ele não é recomendado, para grandes volumes.

    Quando possível teste o código #1 v2. É um exemplo com cursor.

    -- código #1 v2
    declare @produto varchar(50),
            @valor_anual decimal(15, 2),
            @valor_mensal decimal(15, 2),
            @ano int, 
            @ln int = 1;
    declare @ano_anterior int, @soma decimal(15, 2);
    
    declare g_cursor cursor for 
    select * from 
    (
        SELECT
               produto
              ,valor/12 as valor_mensal
              ,valor as valor_anual
              ,ano
        FROM tb_produto
        union all
        SELECT 
               produto
              ,valor/12 as valor_mensal
              ,valor as valor_anual
              ,ano
        FROM tb_produto_historico
    ) as tb 
      where produto != 'Plano Individual'   
      order by ano;
    
    open g_cursor;
    
    fetch next from g_cursor into @produto, @valor_mensal, @valor_anual, @ano;
    set @ano_anterior= @ano;
    set @soma= 0;
    
    while @@FETCH_STATUS = 0 
         begin
         -- verifica se houve quebra de ano
         IF @ano <> @ano_anterior
              begin
              SELECT 'total ano', (@soma / 12), @soma, @ano_anterior;
              set @ano_anterior= @ano;
              set @soma= 0;
              end;
    
         -- exibe detalhe de produto
         select @produto, @valor_mensal, @valor_anual, @ano;
         set @soma= @soma + @valor_anual;
    
         -- lê próximo produto
         fetch next from g_cursor into @produto, @valor_mensal, @valor_anual, @ano
         end;
    
    SELECT 'total ano', (@soma / 12), @soma, @ano_anterior;
    
    CLOSE g_cursor;  
    DEALLOCATE g_cursor;

    Testei com os dados que você postou em sua mensagem inicial e o resultado das somatórias coincidiram.


    José Diz     Belo Horizonte, MG - Brasil     [ Download SQL Server ]


    Este conteúdo é fornecido sem garantias de qualquer tipo, seja expressa ou implícita.

    É isso mesmo que queria!

    Muito obrigado.

    segunda-feira, 3 de fevereiro de 2020 22:05
  • Deleted
    segunda-feira, 3 de fevereiro de 2020 22:23