none
Cursor com SQL RRS feed

  • Pergunta

  • Boa tarde galera, tudo bem?

    Já tentei de tudo e não consigo resolver, talvez tenha alguém aqui que já passou por isso e consiga me ajudar, vamos lá:

    Eu tenho uma tabela mytable

    Código_cli char(4) | Sequencia_reg INT

    0001                    | 1
    0001                    | 2
    0001                    | 3
    0001                    | 4
    0002                    | 5
    0002                    | 6
    0002                    | 7
    0002                    | 8
    0003                    | 9
    0003                    | 10

    O que eu preciso é o seguinte, fazer um update na coluna 2 recomeçando a contagem de sequencias quando muda o código_cli ficando deste jeito:

    Código_cli char(4) | Sequencia_reg INT

    0001                    | 1
    0001                    | 2
    0001                    | 3
    0001                    | 4
    0002                    | 1
    0002                    | 2
    0002                    | 3
    0002                    | 4
    0003                    | 1
    0003                    | 2

    Entendeu??

    Fico no aguardo de uma grande ajuda, muito obrigado.


    Andre Andriotti

    sexta-feira, 6 de junho de 2014 18:43

Respostas

  • André, boa tarde! Tenta assim:

    ;WITH cte_Update (Codigo_cli, Seguencia_reg, nv_Seguencia_reg)

    AS (

    SELECT Codigo_cli, Seguencia_reg,

    RANK() OVER (PARTITION BY Codigo_cli ORDER BY Seguencia_reg)

    FROM mytable )

    UPDATE mytable

    SET Seguencia_reg = nv_Seguencia_reg

    FROM cte_Update c INNER JOIN mytable m

    ON c.Codigo_cli = m.Codigo_cli

    AND c. Seguencia_reg = m.Seguencia_reg

    sexta-feira, 6 de junho de 2014 19:05
  • André,

    Acredito que da forma que você esta trabalhando, esta complicado, pois no decorrer da alteração da Sequência, você esta perdendo o controle da posição e também não tem como identificar qual é o registro.

    Vou postar alguns exemplos, com base, em possíveis situações, um deles é o mais comum, a falta de uma coluna por exemplo que identifique ou apresente a ordem de registros.

    Veja se estes exemplos podem te ajudar:

    Create Table Valores
     (Contador Int Primary Key Identity(1,1),
      Codigo Char(4),
      Sequencia Int)
    
    
    Insert Into Valores Values ('0001',1),('0001',2),('0001',3),('0001',4)
    
    Insert Into Valores Values ('0002',5),('0002',6),('0002',7),('0002',8)
    
    Insert Into Valores Values ('0003',9),('0002',10)
    
    Select * from Valores
    
    Declare @ContadorRegistros Int,
            @ContadorSequencia Int,
    		@ValorColunaCodigo Char(4)
    
    Set @ContadorRegistros=1
    Set @ContadorSequencia=1
    
    While @ContadorRegistros <= (Select Count(Codigo) from Valores)
    Begin
     
     Set @ValorColunaCodigo=(Select Codigo From Valores Where Contador = @ContadorRegistros)
      
     If (@ValorColunaCodigo = (Select Codigo From Valores Where Contador = @ContadorRegistros) And @ContadorRegistros <> 1)
      Set @ContadorSequencia=@ContadorSequencia + 1
     Else
      Set @ContadorSequencia=1
    
    
     Update Valores
     Set Sequencia = @ContadorSequencia
     Where Contador = @ContadorRegistros
     Set @ContadorRegistros += 1
    
    End
    
    Select * from Valores

    Este exemplo vai varrer toda tabela, não é o mais indicado, pois imagine que você tem um volume grande de dados, mas é uma possibilidade.

    Agora uma coisa muito simples que você poderia fazer é utilizar as funções de ranqueamento ou classificação existentes no SQL Server desde a versão 2005.

    Veja este outro exemplo:

    Create Table Valores
     (Codigo Char(4),
      Sequencia Int)
    
    Insert Into Valores Values ('0001',1),('0001',2),('0001',3),('0001',4)
    
    Insert Into Valores Values ('0002',5),('0002',6),('0002',7),('0002',8)
    
    Insert Into Valores Values ('0003',9),('0003',10)
    
    Select * from Valores
    
    Select Codigo, 
           Row_Number() OVER (Order BY Codigo ASC) As NumeroLinha,        
           RANK() OVER (PARTITION BY Codigo ORDER BY Sequencia) As Rank
    From Valores

    Um exemplo utilizando View:

    Create Table Valores
     (Codigo Char(4),
      Sequencia Int)
    
    Insert Into Valores Values ('0001',1),('0001',2),('0001',3),('0001',4)
    
    Insert Into Valores Values ('0002',5),('0002',6),('0002',7),('0002',8)
    
    Insert Into Valores Values ('0003',9),('0003',10)
    
    Select * from Valores
    
    Create View V_Contador
    As
    Select Codigo, 
           Row_Number() OVER (Order BY Codigo ASC) As NumeroLinha,        
           RANK() OVER (PARTITION BY Codigo ORDER BY Sequencia) As NovaSequencia
    From Valores
    
    Select * from V_Contador
    
    UPDATE Valores
    SET Sequencia = vi.NovaSequencia
    FROM Valores V INNER JOIN V_Contador Vi
                        ON V.Codigo = Vi.Codigo
                        AND V.Sequencia = Vi.NumeroLinha
    
    Select * from Valores

    Nem me lembrei da parte de CTE, o Post do Pedro é uma ótima opção.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]




    sexta-feira, 6 de junho de 2014 19:33

Todas as Respostas

  • André, boa tarde! Tenta assim:

    ;WITH cte_Update (Codigo_cli, Seguencia_reg, nv_Seguencia_reg)

    AS (

    SELECT Codigo_cli, Seguencia_reg,

    RANK() OVER (PARTITION BY Codigo_cli ORDER BY Seguencia_reg)

    FROM mytable )

    UPDATE mytable

    SET Seguencia_reg = nv_Seguencia_reg

    FROM cte_Update c INNER JOIN mytable m

    ON c.Codigo_cli = m.Codigo_cli

    AND c. Seguencia_reg = m.Seguencia_reg

    sexta-feira, 6 de junho de 2014 19:05
  • Cara, deu certinho!

    Muito obrigado pela a sua ajuda irmão.....

    Grande abraço.


    Andre Andriotti

    sexta-feira, 6 de junho de 2014 19:20
  • André,

    Acredito que da forma que você esta trabalhando, esta complicado, pois no decorrer da alteração da Sequência, você esta perdendo o controle da posição e também não tem como identificar qual é o registro.

    Vou postar alguns exemplos, com base, em possíveis situações, um deles é o mais comum, a falta de uma coluna por exemplo que identifique ou apresente a ordem de registros.

    Veja se estes exemplos podem te ajudar:

    Create Table Valores
     (Contador Int Primary Key Identity(1,1),
      Codigo Char(4),
      Sequencia Int)
    
    
    Insert Into Valores Values ('0001',1),('0001',2),('0001',3),('0001',4)
    
    Insert Into Valores Values ('0002',5),('0002',6),('0002',7),('0002',8)
    
    Insert Into Valores Values ('0003',9),('0002',10)
    
    Select * from Valores
    
    Declare @ContadorRegistros Int,
            @ContadorSequencia Int,
    		@ValorColunaCodigo Char(4)
    
    Set @ContadorRegistros=1
    Set @ContadorSequencia=1
    
    While @ContadorRegistros <= (Select Count(Codigo) from Valores)
    Begin
     
     Set @ValorColunaCodigo=(Select Codigo From Valores Where Contador = @ContadorRegistros)
      
     If (@ValorColunaCodigo = (Select Codigo From Valores Where Contador = @ContadorRegistros) And @ContadorRegistros <> 1)
      Set @ContadorSequencia=@ContadorSequencia + 1
     Else
      Set @ContadorSequencia=1
    
    
     Update Valores
     Set Sequencia = @ContadorSequencia
     Where Contador = @ContadorRegistros
     Set @ContadorRegistros += 1
    
    End
    
    Select * from Valores

    Este exemplo vai varrer toda tabela, não é o mais indicado, pois imagine que você tem um volume grande de dados, mas é uma possibilidade.

    Agora uma coisa muito simples que você poderia fazer é utilizar as funções de ranqueamento ou classificação existentes no SQL Server desde a versão 2005.

    Veja este outro exemplo:

    Create Table Valores
     (Codigo Char(4),
      Sequencia Int)
    
    Insert Into Valores Values ('0001',1),('0001',2),('0001',3),('0001',4)
    
    Insert Into Valores Values ('0002',5),('0002',6),('0002',7),('0002',8)
    
    Insert Into Valores Values ('0003',9),('0003',10)
    
    Select * from Valores
    
    Select Codigo, 
           Row_Number() OVER (Order BY Codigo ASC) As NumeroLinha,        
           RANK() OVER (PARTITION BY Codigo ORDER BY Sequencia) As Rank
    From Valores

    Um exemplo utilizando View:

    Create Table Valores
     (Codigo Char(4),
      Sequencia Int)
    
    Insert Into Valores Values ('0001',1),('0001',2),('0001',3),('0001',4)
    
    Insert Into Valores Values ('0002',5),('0002',6),('0002',7),('0002',8)
    
    Insert Into Valores Values ('0003',9),('0003',10)
    
    Select * from Valores
    
    Create View V_Contador
    As
    Select Codigo, 
           Row_Number() OVER (Order BY Codigo ASC) As NumeroLinha,        
           RANK() OVER (PARTITION BY Codigo ORDER BY Sequencia) As NovaSequencia
    From Valores
    
    Select * from V_Contador
    
    UPDATE Valores
    SET Sequencia = vi.NovaSequencia
    FROM Valores V INNER JOIN V_Contador Vi
                        ON V.Codigo = Vi.Codigo
                        AND V.Sequencia = Vi.NumeroLinha
    
    Select * from Valores

    Nem me lembrei da parte de CTE, o Post do Pedro é uma ótima opção.


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]




    sexta-feira, 6 de junho de 2014 19:33
  • André, boa tarde! Tenta assim:

    ;WITH cte_Update (Codigo_cli, Seguencia_reg, nv_Seguencia_reg)

    AS (

    SELECT Codigo_cli, Seguencia_reg,

    RANK() OVER (PARTITION BY Codigo_cli ORDER BY Seguencia_reg)

    FROM mytable )

    UPDATE mytable

    SET Seguencia_reg = nv_Seguencia_reg

    FROM cte_Update c INNER JOIN mytable m

    ON c.Codigo_cli = m.Codigo_cli

    AND c. Seguencia_reg = m.Seguencia_reg

    Pedro,

    Show de bola, matou a pau!!!!


    Pedro Antonio Galvão Junior [MVP | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados | SorBR.Net | Professor Universitário | MSIT.com]

    sexta-feira, 6 de junho de 2014 19:38
  • Muito obrigado pela sua colaboração Pedro Antonio Galvão Junior .

    Vou guardar todas as suas dicas como exemplos onde posso usar posteriormente.

    Valeu mesmo.

    Abraços...


    Andre Andriotti

    sexta-feira, 6 de junho de 2014 20:27
  • Opa!...Obrigado!
    sexta-feira, 6 de junho de 2014 20:29