Como todo profesional, el desarrollador web, es una persona, que debe continuamente, buscar herramientas, que le permitan desempeñarse de mejor forma, en su trabajo.

Y pues Internet es una fuente con recursos, tal vez no ilimitados, pero si abundantes, que nos permiten perfeccionar nuestras habilidades, como también adquirir nuevas y lo cual nos ayuda a mantener ese ciclo de continuo aprendizaje que caracteriza a las personas que trabajan en todo lo relacionado, no solo con la tecnología web, sino con la tecnología en general.

Así que les dejo con un muy buen articulo que encontré, hace ya un par de meses, con una, muy buena cantidad de recursos (100, para se exactos), que nos pueden ser de mucha utilidad, entre los cuales, podemos encontrar, desde galerías CSS, tips sobre el correcto uso de HTML y CSS, algunas guias rápidas de referencia para algunos lenguajes de programacion utilizados en el desarrollo web, etc.

Enlace al articulo: I Got 99 Problems, but Developing Ain’t One, 100 Essential Resources for Web Developers

Espero que les guste y lo mas importante, que les sea de utilidad.

Muchas veces nos topamos con la tarea de saber cuales valores de cierta columna(s) son distintos de un conjunto de registros.

Normalmente lo hacemos con la clausula distinct, pues nos ahorra un par de palabras a la hora de escribir el query. Algo como:

select distinct(firstname) from test

Pero el mismo resultado obtenemos si lo hacemos de la siguiente forma:

select firstname from test group by firstname

Entonces, ¿cuál es la diferencia? La diferencia es que con una cantidad considerable de registros, podríamos reducir hasta 1 segundo en el query. Veámoslo con un ejemplo:

Tenemos la tabla test con los siguientes datos (Mostraré solo una parte de la tabla, para ver todos los datos vean el script):



Nombre
codigo1
codigo2
codigo3
Juan 2565368308 35763
Juan 87728636342562659891 2565188276 35801
Mohamad 25653346402565334648 2565334647 35801
Joel 2059330320 2059336400 35205
William 2058700123 2058700227 35209
William 2059789339 2058700227 35594
William 2058700123 2058700227 35202
Elia 2516079797 2058700227 36608
Elia 2516079797 2516390940 36532
Elia 2516079797 2516390940 36608
Elia 2516079797 2516390940 36545

Esta tabla tiene 100 registros y cuando hacemos un DISTINCT sobre la columna firstname el query tarda 110ms en promedio
mientras si lo hacemos con GROUP BY 93 ms. ¿17 ms se preguntarán? Pero si eso sucede con 100 registros y sin nadie más usando la BD, imagínense lo significativo que es el cambio con 2 millones de registros y varias personas haciendo el mismo query al mismo tiempo.

¿A que se debe la diferencia?

Si vemos el plan de ejecución podríamos observar lo siguientes:


-- query con DISTINCT
‘Unique (cost=37.41..39.91 rows=200 width=32) (actual time=0.380..0.462 rows=49 loops=1)’
‘ -> Sort (cost=37.41..38.66 rows=500 width=32) (actual time=0.379..0.409 rows=100 loops=1)’
‘ Sort Key: firstname’
‘ -> Seq Scan on test (cost=0.00..15.00 rows=500 width=32) (actual time=0.015..0.093 rows=100 loops=1)’
‘Total runtime: 0.495 ms’

Aquí el costo de hacer un recorrido secuencial y luego sort, unique es el que aumenta en total el tiempo de ejecución, mientras


-- Haciendo un query con GROUP BY
'HashAggregate (cost=16.25..18.25 rows=200 width=32) (actual time=0.145..0.165 rows=49 loops=1)'
' -> Seq Scan on test (cost=0.00..15.00 rows=500 width=32) (actual time=0.013..0.052 rows=100 loops=1)'
'Total runtime: 0.201 ms'

Se realiza un recorrido secuencial pero se utiliza una función Hash que es más rápida que el sort y el unique.

Así que aunque nos lleve un poco más de tiempo escribir un query con GROUP BY, vamos a recuperarlo cada vez que se ejecute dicho query.

Bueno, pues, una vez más, espero que les sirva y hasta la próxima.

Por cierto, esperen una oleada de artículos entre hoy y mañana pues vamos tratar de subir el nivel del Blog.

Algo muy común en Bases de Datos es importar datos de una a otra, por ejemplo de MySQL a postgres, SQL Server a Oracle, etc. El proceso más simple a mi forma de ver es exportar todo a archivos de texto y luego importarlo de nuevo.

A veces nos topamos con el pequeño problema de que el econding del archivo esta por ejemplo en Latin1 y nuestra base de datos tiene otro encoding (UTF-8 por ejemplo).

Yo me he topado con este problema varias veces, pero usualmente usaba un editor de texto como el textpad para poder guardarlo con otra codificación, y mucho antes de darme cuenta que tenía esa opción, cambiaba caracteres como tildes, ñ, etc con un search and replace. :S.

Pero les cuento que en linux existe un comando que nos soluciona esta tarea.

El comando es iconv :

Simplemente tienen que escribir

iconv myarchivo.txt -f [encoding_actual] -t [encoding_deseado] > mynuevoarchivo.txt

Soporta larga cantidad de encodings, yo creo que todos ( pero no estoy seguro), para ver el listado escriban.

iconv -l

De todos modos lean la documentación oficial , o un simple iconv –help.

Bueno, como siempre espero que les sirva y hasta la próxima, que será dentro de unas cuantas horas. :)

Cuando usamos GROUP BY en un Query, usualmente usamos las funciones de agrupamiento o funciones agregadas, tales como count(), avg(), sum()

Pero a veces se quedan cortas estas operaciones ya que no necesitamos sumar sino concatenar, o la suma no nos sirve sino necesitamos sacar una suma de cuadrados.

Pues en postgres esto es muy sencillo y les voy a dejar un par de ejemplos usando textos:

Vamos a tener 2 tablas (objeto y etiqueta_objeto) con los siguientes datos:

idobjeto
nombre
1
casa
2
perro
3
carro
4
lapiz
5
zapato

idobjeto
etiqueta
1
grande
1
blanca
1
vieja
2
bueno
2
fiel
3
viejo
3
rojo
4
amarillo
4
No 2
5
rojo
5
derecho

Vamos a crear una función para poder concatenar 2 textos usando una "," y luego la vamos a usar en una función agregada :

CREATE OR REPLACE FUNCTION concat(text, text)
RETURNS text AS
$BODY$
DECLARE
t text;
BEGIN
IF character_length($1) > 0 THEN
IF character_length($2) > 0 THEN
t = $1 ||’, ‘|| $2;
else
t = $1;
end if;
ELSE
t = $2;
END IF;
RETURN t;
END;
$BODY$
LANGUAGE ‘plpgsql’ VOLATILE;

Y la función agregada es:

CREATE AGGREGATE concatena(
BASETYPE=text,
SFUNC=concat,
STYPE=text
);

Si quisieramos listar todas las etiquetas de un objeto tendríamos que hacer algo como

SELECT nombre,etiqueta as etiquetas FROM objeto JOIN etiqueta_objeto USING (id_objeto) GROUP BY nombre,etiqueta ORDER BY nombre;

Con esto obtendríamos:

objeto
etiqueta
carro rojo
carro viejo
casa blanca
casa grande
casa vieja
lapiz No 2
lapiz amarillo
perro bueno
perro fiel
zapato derecho
zapato rojo

Si quisieramos obtener un listado con filas con el nombre y el listado de etiquetas separado por comas ("casa";"blanca,grande,vieja"). tendríamos que concatenar cada etiqueta del lado de nuestra progra, o de alguna otra forma (que ahora no se me ocurre, :P). Pero usando la función agregada en el query tenemos:

SELECT nombre,concatena(etiqueta) AS etiquetas FROM objeto JOIN etiqueta_objeto USING (id_objeto) GROUP BY nombre ;


objeto
etiquetas
lapiz amarillo, No 2
zapato rojo, derecho
carro viejo, rojo
perro bueno, fiel
casa grande, blanca, vieja

Esta otra función con hace algo parecido pero en vez de dejarlo en un campo de tipo texto, crea un arreglo con todo las etiquetas (esto por si lo van a utlizar como arreglo, etc).

CREATE AGGREGATE array_accum(
BASETYPE=anyelement,
SFUNC=array_append,
STYPE=anyarray,
INITCOND=’{}’
);

SELECT nombre,array_accum(etiqueta) AS etiquetas FROM objeto JOIN etiqueta_objeto USING (id_objeto) GROUP BY nombre ;

Aquí esta la documentación oficial para crear funciones agregadas en PostgreSQL.

Bueno… pues allí les dejo los Script para probar, y espero que les sirva el ejemplo.

Hasta la próxima y haber quien deja el query para que las etiquetas salgan en orden alfabético, se los dejo de tarea :). Saludos!

Cerrar
Enviar por Correo