Usuário com melhor resposta
Cursor com SQL

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 | 10O 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 | 2Entendeu??
Fico no aguardo de uma grande ajuda, muito obrigado.
Andre Andriotti
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
- Editado Pedro Vitor de Oliveira Gonçalves sexta-feira, 6 de junho de 2014 19:07
- Sugerido como Resposta Pedro Vitor de Oliveira Gonçalves sexta-feira, 6 de junho de 2014 19:23
- Marcado como Resposta Andriotti sexta-feira, 6 de junho de 2014 19:42
-
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]
- Editado Junior Galvão - MVPMVP sexta-feira, 6 de junho de 2014 19:53
- Marcado como Resposta Andriotti sexta-feira, 6 de junho de 2014 20:30
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
- Editado Pedro Vitor de Oliveira Gonçalves sexta-feira, 6 de junho de 2014 19:07
- Sugerido como Resposta Pedro Vitor de Oliveira Gonçalves sexta-feira, 6 de junho de 2014 19:23
- Marcado como Resposta Andriotti sexta-feira, 6 de junho de 2014 19:42
-
-
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]
- Editado Junior Galvão - MVPMVP sexta-feira, 6 de junho de 2014 19:53
- Marcado como Resposta Andriotti sexta-feira, 6 de junho de 2014 20:30
-
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]
-
-