Vous êtes sur la page 1sur 4

Como hacer en SQLServer un update a partir de una select

con registros agregados


Submitted by carlos on 21 August, 2013 - 19:05

SQL

SQLServer

tips

Transact-SQL

Update

Bases de datos

Una manera muy potente de hacer un Update de una tabla en una base de datos SQL Server es
enlazando la tabla con otra con una join, y actualizando los campos de cada registro de la primera a
partir de los valores de los campos del registro enlazado de la segunda. Esta tcnica ya la
comentamos hace tiempo en el foro como Update con join o update from select en SQL Server.

Un ejemplo de Update con join sera esta sentencia:


Update tabla1
set tabla1campo1 = t2.tabla2campo1
from tabla1 t1, tabla2 t2
where t1.campoX = t2.campoX

Si el campo por el que se hace la join es clave en la segunda tabla, no hay ningn problema, el
update funcionar perfectamente. El problema lo tendremos cuando no sea as y al enlazar por ese
campo, a cada registro de la primera tabla le pueda corresponder ms de uno de la segunda. En ese
caso, podemos encontrarnos con resultados no esperados, ya que la actualizacin se realizar con el
valor de slo uno de los registros con los que enlace cada registro de la primera tabla.
Si es lo que buscamos ya est bien, pero si la correspondencia es de uno a varios registros y lo que
queremos es guardar en cada campo de la primera tabla un valor agregado, como por ejemplo la
suma, de todos los registros que tienen correspondencia en la segunda tabla, tendremos que
complicar un poco ms la sentencia.

Cmo hacer un update con join a partir de registros agregados


La primera solucin que se nos puede ocurrir es utilizar directamente la funcin de agregacin en el
SET, al asignar el valor del campo de la segunda tabla sobre el de la primera. Sera algo as como:
Update tabla1
set tabla1campo1 = sum(t2.tabla2campo1)
from tabla1 t1, tabla2 t2
where t1.campoX = t2.campoX

Hemos aadido una funcin sum al asignar el segundo campo. Sera genial que SQL Server
entendiera as lo que queremos hacer, pero no, el resultado que el motor nos devolvera con esta
sentencia de Transact SQL sera el siguiente error:
Mens. 157, Nivel 15, Estado 1, Lnea 2
No puede aparecer un agregado en la lista establecida en una instruccin UPDATE.

Y entonces qu hacemos? Pues una solucin sencilla es crear una vista o un alias que devuelva al
UPDATE el resultado de la agregacin de la segunda tabla, y haga que la join del update encuentre
en esta vista un slo registro para cada registro de la tabla a actualizar.
Se trata de crear una vista o un alias de tabla con la join de las dos tablas y el valor agregado para
cada registro de la tabla origen sobre la que queremos hacer el update.
La informacin que necesitamos son los campos clave de cada registro de la tabla, y el
valor calculado para cada uno de ellos.
Esta sera la SELECT con los identificadores y el valor agregado para cada registro de la tabla
origen:
SELECT campoX, SUM(t2.tabla2campo1)
FROM tabla1 t1, tabla2 t2
WHERE t1.campoX=t2.campoX
GROUP BY t1.campoX

Entonces la sentencia de Update utilizando esta select con un alias quedara de la siguiente manera:

UPDATE tabla1
SET tabla1campo1 = tabla2agregada.campo1agregado
FROM tabla1 t1, (SELECT campoX, SUM(t2.tabla2campo1) campo1agregado
FROM tabla1 t1, tabla2 t2
WHERE t1.campoX=t2.campoX
GROUP BY t1.campoX) tabla2agregada
WHERE t1.campoX = tabla2agregada.campoX

Y de esta manera en cada registro de la primera tabla, al campo1 se le asignara la suma de los
valores de tabla2campo1 que enlazaran haciendo la join con la otra tabla por campoX.
Puede ser muy til cuando queremos actualizar campos de tablas con valores de otras tablas que
estn a diferentes niveles de agregacin. Por ejemplo, el importe en una tabla de cabeceras de
facturas, calculado a partir de los importes de otra tabla que contiene las lineas o el detalle de esas
facturas.
Conoces o se te ocurre alguna manera ms eficiente, ms elegante o simplemente distinta de
conseguir lo mismo?

Usando la versin 4 (o superior) de MySQL es posible actualizar un valor en una tabla en base al valor de
un campo en otra tabla distinta. Para ello se utiliza un JOIN entre las dos tablas, por ejemplo supongamos
que en un sistema tenemos dos tablas llamadas productos (que almacenara los datos de los productos de
un catlogo) y pedidosLineas (que almacenara las lneas correspondientes a un pedido) y que en cierto
momento deseamos actualizar el precio de una lnea de producto resetendola a su valor original (que
estara en la tabla productos):

UPDATE productos origen, pedidosLineas destino

SET destino.precio = origen. Precio

WHERE destino.idProducto = origen.id AND destino.id=123;

Otro ejemplo podra ser aumentar un 15% el precio de los productos que cumplan cierta condicin.
Supongamos que por algn motivo los precios se encuentran en una tabla (productosPrecio) diferente a
la que contiene los detalles de los productos:

UPDATE productos p, productosPrecio pp

SET pp.precio = pp. precio * 0.15

WHERE p.idProducto = pp. idProducto

AND p.fecha < '2012-01-01'

El mismo resultado se podra obtener haciendo un INNER JOIN:

UPDATE productos p

INNER JOIN productosPrecio pp ON pp. idProducto = p.idProducto

SET pp.precio = pp. precio * 0.15

WHERE p.fecha < '2012-01-01'

Tambin sera posible actualizar simultneamente campos de todas las tablas incluidas en el JOIN:

UPDATE productos p

INNER JOIN productosPrecio pp ON pp. idProducto = p.idProducto

SET pp.precio = pp. precio * 0.15, p.update = NOW()

WHERE p.fecha < '2012-01-01'

Ms informacin en el Manual de Referencia de MySQL:

Vous aimerez peut-être aussi