<?xml version='1.0' encoding='UTF-8'?>
<elementos_gw>
  <documento>
    <id>2895</id>
    <autor>5</autor>
    <nome>Usando dados de outra linha no UPDATE</nome>
    <nome_facil>usando dados de outra linha no update</nome_facil>
    <criacao>2012-05-22 19:43:49</criacao>
    <alteracao>2012-05-28 19:38:16</alteracao>
    <texto>O problema: eu tenho uma tabela com //nome//, //num// e //dif//. O que é atípico aqui é que //dif// deve ser atualizado com a diferença entre dois //nums// consecutivos para o mesmo nome. Então eu preciso conhecer o //num// da próxima linha (para o mesmo nome) para atualizar a atual. E eu quero fazer isso em SQL com um //único// UPDATE.

Aqui eu estou assumindo que as linhas devam ser ordenadas pelo //num//, mas poderia ser por outro campo, como //id// ou //timestamp//.

A solução em MySQL é usar uma tabela temporária para pegar o //num// da próxima linha e associá-la com o id da atual, e usar essa tabela no UPDATE.

Segue o código. Divirta-se! ;-)

{{{
-- a tabela usada para teste (sintaxe MySQL)
CREATE TABLE IF NOT EXISTS `teste` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(30) NOT NULL,
  `num` int(11) NOT NULL,
  `dif` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

-- alguns valores para brincar
INSERT INTO `teste` (`id`, `nome`, `num`, `dif`) VALUES
(1, &#039;a&#039;, 10, NULL),
(2, &#039;b&#039;, 8, NULL),
(3, &#039;a&#039;, 18, NULL),
(4, &#039;a&#039;, 21, NULL),
(5, &#039;b&#039;, 14, NULL),
(6, &#039;a&#039;, 32, NULL),
(7, &#039;b&#039;, 20, NULL),
(8, &#039;b&#039;, 21, NULL);

-- uma query para testar a capacidade de pegar o dif desejado
select id, nome, num, (select min(num) from teste where nome = t1.nome and num &gt; t1.num)-num
from teste t1
where dif is null
order by nome, num;

-- atualizando a tabela com o dif calculado com o num de outra linha
update teste t2, (
  select id, (select min(num) from teste where nome = t1.nome and num &gt; t1.num)-num as dif
  from teste t1
) t3
set t2.dif = t3.dif
where t2.id = t3.id
and t2.dif is null

-- uma query alternativa para tornar possível obter mais de uma coluna (em t2)
select t1.id, t1.nome, t1.num, t2.nome, t2.num
from teste t1, teste t2
where  t2.id = (select id from teste where nome = t1.nome and num &gt; t1.num order by num limit 1)
order by t1.nome, t1.num
}}}

//See this post in [http://rubychallenger.blogspot.com.br/2012/05/how-to-update-table-using-data-from.html English].//</texto>
    <publico>1</publico>
    <original>0</original>
    <anterior>0</anterior>
    <versao>0</versao>
    <traducao>0</traducao>
    <propriedade>
      <nome>categ</nome>
      <valor>soluções</valor>
      <publico>1</publico>
    </propriedade>
    <propriedade>
      <nome>categ</nome>
      <valor>list</valor>
      <publico>1</publico>
    </propriedade>
    <propriedade>
      <nome>categ</nome>
      <valor>dicas</valor>
      <publico>1</publico>
    </propriedade>
    <propriedade>
      <nome>assunto</nome>
      <valor>sql</valor>
      <publico>1</publico>
    </propriedade>
    <propriedade>
      <nome>assunto</nome>
      <valor>mysql</valor>
      <publico>1</publico>
    </propriedade>
    <propriedade>
      <nome>área</nome>
      <valor>informática</valor>
      <publico>1</publico>
    </propriedade>
  </documento>
</elementos_gw>
