Friday, January 12, 2007

Obtener los N máximos valores.

Hoy me topé con el problema de encontrar los N primeros valores de la columna 10, de una información que se encontraba en texto plano separado por comas.

Sé que la solución más fácil (pero no necesariamente la más óptima) sería utilizar algo como este oneliner:

 cut -d, -f10 archivo | sort -rn | head -20

Pero como siempre me interesa hacerme la vida un poco más difícil, pensé en hacerlo en AWK, para lo cual utilicé el siguiente oneliner:

 awk -F, -v T=20 '{ V=int($10); C=0; for(i=0;i<T && C==0;i++)if(V>F[i]){ C++; for(j=T-1;j>i;j--) F[j]=F[j-1]; F[i]=V } };
END{ for(i=0;i<T;i++) print F[i] }'

Luego de tomar algunos tiempos en segundos, verifiqué cuál era el método más rápido:

awk: 294s 296s 296s
cut+sort: 91s 88s 91s

Si, el burdo método del cut+sort es el más rápido, pero aún así prefiero el método AWK, el porqué es muy simple: awk me obliga a pensar,de manera lógica, acerca de cómo debo atacar el problema.

Cut y sort, no me obligan a pensar nada, ya están allí y simplemente tendría que usarlos, pero para usar cosas que no me obligan a pensar tengo más que de sobra.

BTW: el archivo mide algo más de 300mb comprimido, y los tiempos aquí incluyen la decompresión en línea. El número de registros es de algo más de 13 millones, la máquina obviamente no es una XT (como muchos pensarían de mí).

BTW2: acabo de recordar que tengo que utilizar htmlentities para publicar el código con comparaciones "menor que" o "mayor que".

--
KIT

Labels:

Wednesday, January 10, 2007

Cambiar tamaño de columna en PostgreSQL

Hoy me topé con un problema, tenía que cambiar el tamaño de una columna en PostgreSQL, y google no me estaba ayudando mucho, pues el manual del ALTER TABLE no documenta nada acerca de cómo lograr este cambio, pero después de googlear un rato logré encontrar la solución al problema en este link.

La solución es bastante fácil, y denota la ventaja de tener atributos en vez de amarrar en el almacenamiento esta declaración (en este caso, la longitud de una columna).

Yo no soy muy entendido de bases de datos, ni de las herramientas que puedan existir para evitar estar cambiando la longitud de las columnas, así que a quien le interese, le dejo un script en AWK que hace justamente eso, calcular el máximo de longitud de cada columna.

 BEGIN {
FS=","
}
{
for (i=1; i<=NF; i++)
if (length($i)>MAX[i])
MAX[i]=le
}
END {
print "maximos por campo"
for (i in MAX)
print i "->" MAX[i]
}
Y sólo tienen que asignar a la variable "FS" el valor correcto para el separador de campos, y lo invocan así:

 awk -f archivo.awk archivo_datos.txt

Si el archivo tiene terminación de líneas de tipo "crlf", tienen que filtrar el "\r" o de lo contrario, AWK no funcionará como se espera:

 sed 's/\r//' archivo_datos.txt | awk -f archivo.awk

Espero que a alguno le sirva...



KIT

Labels: