<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Codigo Manso &#187; SQL</title>
	<atom:link href="http://www.codigomanso.com/es/category/programacion/sql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.codigomanso.com</link>
	<description>Programación, informática y tecnología</description>
	<lastBuildDate>Sun, 21 Aug 2011 10:54:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Truco Manso: Actualizar el orden de una fila sin tocar el resto</title>
		<link>http://www.codigomanso.com/es/2009/01/update-order-of-a-row-keeping-the-rest-untouched/</link>
		<comments>http://www.codigomanso.com/es/2009/01/update-order-of-a-row-keeping-the-rest-untouched/#comments</comments>
		<pubDate>Sat, 31 Jan 2009 10:55:24 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programacion]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Add new tag]]></category>
		<category><![CDATA[fila]]></category>
		<category><![CDATA[orden]]></category>
		<category><![CDATA[tabla]]></category>
		<category><![CDATA[truco manso]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/es/?p=506</guid>
		<description><![CDATA[Por salirme un poco de javascript y PHP, ahora una de bases de datos.
Este artículo trata sobre como cambiar el orden de un elemento dentro de una tabla, manteniendo el orden relativo de todos los demás elementos y actualizando únicamente un campo. Como esta descripcción es un poco densa, vayamos por partes.
Por simplificar el ejemplo, [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Por salirme un poco de javascript y PHP, ahora una de bases de datos.</p>
<p style="text-align: justify;">Este artículo trata sobre como cambiar el orden de un elemento dentro de una tabla, manteniendo el orden relativo de todos los demás elementos y actualizando únicamente un campo. Como esta descripcción es un poco densa, vayamos por partes.</p>
<p style="text-align: justify;">Por simplificar el ejemplo, digamos que estoy haciendo un sitio web relacionado con el mundo del motor, y como todo sitio web que se precie, tengo una base de datos. En esa base de datos hay dos tablas, una tabla <strong>marcas</strong> y otra tabla <strong>modelos.</strong> En la tabla <strong>marcas</strong> hay una fila por cada marca de coches (Toyota, Honda, Hyunday, Mercedes, Chrysler, BMW, Audi, &#8230;), y en la tabla de <strong>modelos</strong> de coches, pues hay una serie de modelos para cada tipo de coche. Por ejemplo, para Audi, estaría el modelo A6 2.0 TDIe , A5 2.0 TDI, A4, TT &#8230;, y la lista sigue hasta donde uno quiera y más para cada marca. Creo que con esto uno ya se hace una idea de las tablas que hay.</p>
<p style="text-align: justify;">El tema es que en mi sitio web, yo quiero que cuando el usuario haga click en una marca, le salga una lista ordenada de los modelos disponibles para esa marca, pero no quiero un orden cualquiera, no quiero que salgan ni por nombre, ni por votos, ni por precio, quiero que por defecto salga por el orden específico que yo haya definido.</p>
<p style="text-align: justify;">Pensareis, pues fácil, simplemente hay que añadir un campo <strong>orden</strong> dentro de la tabla <strong>modelos</strong>, o si os gusta tener las tablas normalizadas al máximo, pues creariais una tabla extra donde meteriais dos claves ajenas, una a <strong>modelos </strong>y otra a <strong>marcas</strong> y luego pondriais el campo<strong> orden.</strong></p>
<p style="text-align: justify;">Se haga de la forma A o de la forma B, el concepto final es que hay un campo que se llama orden, y que para lo que me sirve es para definir manualmente el orden en el que quiero que salgan los modelos en la página principal.</p>
<table style="float: left; width: auto;">
<tr>
<th>Marca</td>
</tr>
<tr>
<td>Nombre</td>
</tr>
<tr>
<td>Descripción</td>
</tr>
<tr>
<td>Imagen</td>
</tr>
<tr>
<td>&#8230;</td>
</tr>
</table>
<table style="float: left; margin-left: 2em;  width: auto;">
<tr>
<th>Modelo</td>
</tr>
<tr>
<td>Nombre</td>
</tr>
<tr>
<td>Descripción</td>
</tr>
<tr>
<td>Imagen</td>
</tr>
<tr>
<td>&#8230;</td>
</tr>
<tr>
<td><b>Orden</b></td>
</tr>
<tr>
<td>&#8230;</td>
</tr>
</table>
<div style="clear:both;"></div>
<p style="text-align: justify;">Hasta aquí sólo es introducción al artículo, lo bueno viene ahora.</p>
<p style="text-align: justify;">Imaginad que en marcas sólo está Audi (por decir una), y que sólo hay 4 modelos en la base de datos A3, A4, A5 y TT. A partir de aquí vamos a hacer como si las marcas no existieran (por simplificar aún más). Así que se nos queda una tabla de modelos como sigue:</p>
<table style="width: auto;">
<tr>
<th>Nombre</th>
<th>Descripción</th>
<th>&#8230;</th>
<th><b>Orden</b></th>
<th>&#8230;</th>
</tr>
<tr>
<td>A3</td>
<td>El A3 mola</td>
<td>&#8230;</td>
<td><b>1</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A4</td>
<td>El A4 mola más</td>
<td>&#8230;</td>
<td><b>2</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A5</td>
<td>El A5 mola mucho más</td>
<td>&#8230;</td>
<td><b>3</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>TT</td>
<td>Sin duda es el mejor</td>
<td>&#8230;</td>
<td><b>4</b></td>
<td>&#8230;</td>
</tr>
</table>
<p style="text-align: justify;">Ahora, si yo en mi sitio web, hago un select, y ordeno por el campo <b>orden</b>, pues como es lógico, viendo esa tabla, primero saldrá el A3, luego el A4, luego el A5 y seguidamente el Audi TT.</p>
<h5>El problema:</h5>
<p style="text-align: justify;"><b>¿Cómo hago ahora, si quiero que el Audi TT salga el primero?</b></p>
<p style="text-align: justify;">Se debe tener en cuenta, que yo sólo quiero mover el Audi TT a la primera posición, pero quiero que el A3, A4 y A5 no cambien su orden relativo. Y he dicho la primera posición por decir algo, pero también podría querer que el TT apareciera entre el A3 y el A4.</p>
<p style="text-align: justify;">
<h5>Solución 1: la fácil</h5>
<p style="text-align: justify;">Bueno, pues lo primero que a uno le viene a la cabeza (al menos a mi), es básicamente incrementar en 1 todos los campos cuyo orden sea mayor al que yo voy a poner para TT, y luego actualizar el orden del TT.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">UPDATE</span> modelo <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #66cc66;">=</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #66cc66;">+</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">WHERE</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #66cc66;">&gt;=</span> <span style="color: #cc66cc;">1</span>;
<span style="color: #993333; font-weight: bold;">UPDATE</span> modelo <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">WHERE</span> name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'TT'</span>;</pre></div></div>

<p style="text-align: justify;">Básicamente arriba he utilizado 2 queries, uno de complejidad lineal que modifica una ristra de filas, y otro que sólo toca una tabla.</p>
<p style="text-align: justify;">Como esta solución no me convencía demasiado, no era muy bonita, pues me puse a pensar y se me ocurrió otra.</p>
<p style="text-align: justify;">
<h5>Solución 2: la magia de los float</h5>
<p style="text-align: justify;"><b>¿Y si en vez de un entero, se usa un número real?</b></p>
<p style="text-align: justify;">Si el campo <b>orden</b> fuera real, entonces podría saber cual es el orden de los elementos inmediatamente anterior y posterior (puesto que los he cargado en el interfaz de usuario de mi web), y podría actualizar sólo el campo del TT sin tocar ningún otro elemento de la tabla.</p>
<p style="text-align: justify;">Es decir, si tenemos la configuración inicial (A3, A4, A5, TT), y quiero que el TT esté entre A3 y A4, como A3 tiene el valor de orden igual a 1.0, y A4 tiene el valor de orden de 2.0, y quiero que TT esté enmedio, el tema quedará de la siguiente manera.</p>
<table style="width: auto;">
<tr>
<th>Nombre</th>
<th>Descripción</th>
<th>&#8230;</th>
<th><b>Orden</b></th>
<th>&#8230;</th>
</tr>
<tr>
<td>A3</td>
<td>El A3 mola</td>
<td>&#8230;</td>
<td><b>1</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>TT</td>
<td>Sin duda es el mejor</td>
<td>&#8230;</td>
<td><b>1.5</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A4</td>
<td>El A4 mola más</td>
<td>&#8230;</td>
<td><b>2</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A5</td>
<td>El A5 mola mucho más</td>
<td>&#8230;</td>
<td><b>3</b></td>
<td>&#8230;</td>
</tr>
</table>
<p style="text-align: justify;">Básicamente lo que he hecho es calcular el valor intermedio entre A3 y A4, vease (1.0 + 2.0) / 2</p>
<p style="text-align: justify;">Nótese que esto se puede hacer tantas veces como se quiera, que siempre habrá un orden entre los elementos y <em>&#8220;jamás&#8221;</em> habrá dos elementos con el mismo orden. Por ejemplo, si ahora quermos que el A4 esté entre el A3 y el TT, actualizaríamos el orden de A4 a <b>(1.0 + 1.5)/2 = 1.25</b>.</p>
<table style="width: auto;">
<tr>
<th>Nombre</th>
<th>Descripción</th>
<th>&#8230;</th>
<th><b>Orden</b></th>
<th>&#8230;</th>
</tr>
<tr>
<td>A3</td>
<td>El A3 mola</td>
<td>&#8230;</td>
<td><b>1</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A4</td>
<td>El A4 mola más</td>
<td>&#8230;</td>
<td><b>1.25</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>TT</td>
<td>Sin duda es el mejor</td>
<td>&#8230;</td>
<td><b>1.5</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A5</td>
<td>El A5 mola mucho más</td>
<td>&#8230;</td>
<td><b>3</b></td>
<td>&#8230;</td>
</tr>
</table>
<p style="text-align: justify;">Como veis, el procedimiento está chupado, y sólo hay que tocar un campo.</p>
<p style="text-align: justify;">Claro, ahora surgen varias preguntas. Me direis, que bonito, <b>¿y que pasa si quieres ponerlo en la primera posición?</b> Fácil, si desde el principio se asume que el orden de los elementos que insertamos empieza en 1.0, entonces el elemento posterior será el que ya exista en la base de datos, y el elemento anterior será cero (0.0)</p>
<p style="text-align: justify;"><b>¿Y que pasa si ahora quieres insertar el A6?</b> Pues pasa que si hay 4 elementos, el A6 habrá que insertarlo con el valor 5.0 (nunca habrá colisión si se hace como <b>número de elementos + 1</b>).</p>
<p style="text-align: justify;">Y la pregunta estrella es: &#8220;<i>oye, los números de punto flotante tenían un límite, ¿no?</i> <b>¿que pasa si se desbordan?</b>&#8221; Ah, amigo Sancho ¡Con la iglesia hemos topado!</p>
<p style="text-align: justify;">Si os fijais, hacer que se desborde es tan fácil como ir moviendo todos los elementos siempre a la misma posición. Por ejemplo, si está el orden 1 y 2 inicialmente, y movemos el 3 a la segunda posición, ahora será 1, 1.5 y 2, luego si movemos el 2 a la segunda posición será 1, 1.25 y 1.5, si volvemos a mover el 1.5 a la segunda posición será 1, 1.125 y 1.25, y así sucesivamente hasta que el punto flotante diga hasta aquí (que puede ser mas o menos despues de unas 20 veces, según el número de bits que se usen para decimales).</p>
<p style="text-align: justify;">Lo cual nos lleva a la solución 3</p>
<h5>Solución 3: tapando agujeros</h5>
<h6>Solución 3.1: proceso en background</h6>
<p style="text-align: justify;">Una solución podría ser tener un proceso que una vez al día, a la semana o al mes, actualice todos los elementos de la tabla a números enteros respetando su orden actual. Aunque para eso casi mejor implementar la solución 1 que es más mantenible. Lo cual nos lleva a buscar otra alternativa.</p>
<h6>Solución 3.2: actualización entera </h6>
<p style="text-align: justify;">Básicamente es igual que la solución 2 (no me repetiré), pero con una salvedad, y es que cuando se mueva un elemento a una posición, si no hay ningún número entero en esa posición se tratará de redondear al número entero hacia abajo (o hacia arriba, o ambos), para mitigar esa degradación de los flotantes que van teniendo cada vez más decimales.</p>
<p style="text-align: justify;">Vease un ejemplo. Imaginemos que el tema se ha degradado un poco y parto de la siguiente configuración:</p>
<table style="width: auto;">
<tr>
<th>Nombre</th>
<th>Descripción</th>
<th>&#8230;</th>
<th><b>Orden</b></th>
<th>&#8230;</th>
</tr>
<tr>
<td>A3</td>
<td>El A3 mola</td>
<td>&#8230;</td>
<td><b>1.125</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>TT</td>
<td>Sin duda es el mejor</td>
<td>&#8230;</td>
<td><b>1.0394</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A4</td>
<td>El A4 mola más</td>
<td>&#8230;</td>
<td><b>1.7628</b></td>
<td>&#8230;</td>
</tr>
<tr>
<td>A5</td>
<td>El A5 mola mucho más</td>
<td>&#8230;</td>
<td><b>3.78</b></td>
<td>&#8230;</td>
</tr>
</table>
<p style="text-align: justify;">Si ahora muevo el A3, entre el A4 y el A5, de normal haría lo siguiente: (1.7628 + 3.78)/2 = 2.7714. Pero oh magia, si redondeo el 2.7714 hacia abajo me da 2, y resulta que el sigue estando entre 1.7628 y 3.78, por lo tanto en vez de actualizar a 2.7714 actualizaría a 2. De esta manera, si más tarde moviera el TT entre el A3 y el A5, en vez de hacer esta operación <b>(2.7714 + 3.78) / 2</b>, tendría que hacer esta <b>(2 + 3.78) / 2</b>, que obviamente tiene menos decimales.</p>
<p style="text-align: justify;">Nótese que para esta solución símplemente hay que mirar si el número entero sigue estando entre el número anterior y el posterior (que son conocidos) y no es igual a ninguno de ambos.</p>
<p style="text-align: justify;">Además, si se asume que movimiento de los elementos se hará de forma aleatoria, de esta manera es poco probable (aunque sigue siendo posible) que al final el punto flotante se desborde.</p>
<p style="text-align: justify;">Por cierto, esta solución ahora mismo la he presentado con números reales, pero se pueden usar perfectamente números enteros, aunque siguiendo otro esquema.</p>
<h5>Conclusión</h5>
<p style="text-align: justify;">Si quieres robustez, usa la solución 1 para mantener el orden de todos los elementos; si quieres actualizar un único elemento cada vez, porque es una operación que se va a realizar miles de veces por miles de personas al día lo recomendable es la solución 3.2, aunque tendría problemas si hay varias personas concurrentemente actualizando campos.
<p style="text-align: justify; font-weight: bold;">Finalmente, aunque en el artículo se han visto un par de soluciones (con sus parches), me encantaría saber si alguien conoce otras soluciones o sabe que problemas tienen en la práctica las que yo he puesto.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2009/01/update-order-of-a-row-keeping-the-rest-untouched/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Crear varios millones de registros usando SQL</title>
		<link>http://www.codigomanso.com/es/2008/12/crear-varios-millones-de-registros-usando-sql/</link>
		<comments>http://www.codigomanso.com/es/2008/12/crear-varios-millones-de-registros-usando-sql/#comments</comments>
		<pubDate>Wed, 10 Dec 2008 17:39:41 +0000</pubDate>
		<dc:creator>Pau Sanchez</dc:creator>
				<category><![CDATA[Programacion]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[insert]]></category>
		<category><![CDATA[registros]]></category>

		<guid isPermaLink="false">http://www.codigomanso.com/?p=265</guid>
		<description><![CDATA[Me gusta bastante la forma que comentan en Tu función sobre como insertar 8 millones de datos usando sólo SQL.
Básicamente consiste en insertar unos valores semilla, y posteriormente ejecutar:

INSERT INTO t SELECT * FROM t;


Con lo cual se insertan de nuevo los elementos existentes en la iteración anterior. Claramente el crecimiento es exponencial (2n), y [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Me gusta bastante la forma que comentan en <a href="http://www.tufuncion.com/" target="_blank">Tu función</a> sobre como <a href="http://www.tufuncion.com/test-mysql" target="_blank">insertar 8 millones de datos usando sólo SQL</a>.</p>
<p style="text-align: justify;">Básicamente consiste en insertar unos valores semilla, y posteriormente ejecutar:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> t <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> t;</pre></div></div>

<p style="text-align: justify;">
<p style="text-align: justify;">Con lo cual se insertan de nuevo los elementos existentes en la iteración anterior. <em>Claramente el crecimiento es exponencial</em> <strong>(2<sup>n</sup>)</strong>, y partiendo de un único campo en la base de datos, en tan solo 23 iteraciones se consiguen 8.388.608 datos (la verdad es que 8 millones de registros ya son registros).</p>
<p style="text-align: justify;">Yo hasta ahora hacía iteraciones de sentencias insert en PHP&#8230; la próxima vez me lo replantearé <img src='http://www.codigomanso.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.codigomanso.com/es/2008/12/crear-varios-millones-de-registros-usando-sql/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

