jueves, agosto 31, 2006

La funcion DISTINCT (PostgreSQL/SQL Server)

Bueno la historia comenzo cuando en una base de datos de SQL Server se necesitaban eliminar de una tabla unos datos duplicados, aunque soy nuevo en la oficina donde laboro dije que podia asumir el reto, pero naaa no pude hacerlo, tratando de mirar las posibles soluciones para almenos sacar la informacion que se necesitaba, recorde que en PostgreSQL existe una funcion llamada DISTINCT ON la cual tambien existe en SQL Server pero el comportamiento de esta al agregar varios campos no daba el resultado que necesitaba, es decir era lo mismo utilizar un DISTINCT que un GROUP BY, entonces con mas calma decide hacer pruebas en mi equipo con Postgres para saber la forma de hacerlo. Realizando las pruebas lo primero que note es que no es lo mismo DISTINCT a DISTINCT ON, el DISTINCT ON si retorna solo una fila unica descartando las demas y con esta funcion si tenia los resultados esperados pero esta no existia en SQL Server y tomando en cuenta que en el manual de PostgreSQL indicaban que la funcion DISTINCT ON podia retornar resultados inesperados entonces segui en busca de encontrar una solucion para ambos motores de base de datos. Ya habia intentado de varias formas obtener el resultado con subquery y el group by pero sin buenos resultados, Googleando un poco encontre la siguiente pagina donde ya alguien habia tenido el mismo inconveniente pero indico un sql donde habia obtenido los mismo resultados, observando el sql me di cuenta que se utilizaba la funcion MIN() entonces decidi realizar las pruebas:
--con distinct
SELECT DISTINCT ON (campo1) * FROM prueba2;
--sin el distinct to
SELECT b.* FROM ( SELECT campo1, min(campo6) as campo6 FROM prueba2 GROUP BY campo1 ) a, prueba2 b WHERE a.campo1=b.campo1 AND a.campo6=b.campo6
eso era lo que faltaba utilizar era una funcion MIN()/MAX() para obtener el resultado esperado, ya habia conseguido la solucion a la primera parte del problema.

La segunda parte es mas sencilla, eliminar los registros duplicados, esto lo consegui de la siguiente forma: creando una tabla temporal donde se registraran los datos unicos, luego se elimina los datos de la tabla principal y luego se vuelcan los datos de la tabla temporal a la principal como tabla temporal (en PostgreSQL):
CREATE TEMP TABLE temporal AS SELECT b.* FROM ( SELECT campo1, min(campo6) as campo6 FROM prueba2 GROUP BY campo1 ) a, prueba2 b WHERE a.campo1=b.campo1 AND a.campo6=b.campo6
o sencillamente asi: (de esta forma funciona en PostgreSQL y SQL Server)
SELECT b.* INTO temporal FROM ( SELECT campo1, min(campo6) as campo6 FROM prueba2 GROUP BY campo1 ) a, prueba2 b WHERE a.campo1=b.campo1 AND a.campo6=b.campo6;
luego eliminamos los datos (la funcion truncate tambien es soportada por sql server o almenos eso dicen los manuales)
TRUNCATE prueba2;
y por ultimo
INSERT INTO prueba2 SELECT * FROM temporal;
En postgreSQL creandose la tabla temporal no hubiera sido necesario eliminar la entidad, dado que esta desaparece cuando se termina la sesion, pero no siendo el caso para la sentencia INSERT [..] INTO [], entonces:
DROP TABLE temporal;
Bueno aunque lo anterior no es el santo grial, es un truco para salir de apuros o para alguien que no conociera una forma de hacerlo, espero que a alguien le sirva, almenos a mi me sirvio.

sábado, agosto 26, 2006

Lexmark T430 en slackware 10.2

Bueno aqui dejo la experiencia de como instalar los drivers de esta impresora en slackware 10.2.

Primero que todo esta impresora la habia configurado en CentOS release 4.2 y dado que Lexmark tiene unos driver muy bien elaborados para Red-Hat y Suse (son los que viene en el cd de la impresora), pero ademas tiene soporte para mas distribuciones (drivers impresora)
pero no para slackware, entonces decidi hacer lo siguiente en base a la instalacion que ya tenia en un CentOS.

1. Convertir el rpm a un tgz (rpm2tgz /mnt/cdrom/unix/packages/print-drivers-linux-glibc2-x86.rpm)
2. Instalar el paquete que se creo (intallpkg print-drivers-linux-glibc2-x86.tgz)
3. Tener en cuenta que debe estar corriendo algun sistema de impresion, en mi caso es CUPS, por lo tanto levanten el servicio (/etc/rc.d/rc.cups)
4. Ejecutar el siguiente script /usr/local/lexmark/setup.lexprint, este script pedira algunos datos de configuracion, ademas que tambien solicitara manejar el script de arranque del cups (si lo desean) entonces para evitar de que salga un error por esto se puede hacer lo siguiente:
* modificar el archivo setup.lexprint he indicar donde esta el servicio de cups, recuerde que el script viene para red-hat y su familia por lo tanto lo buscara en /etc/init.d/cups
* realizar un enlace a /etc/rc.d/rc.cups (#ln -s /etc/rc.d/ /etc/init.d #ln -s rc.cups cups)
5. Luego de ejecutar el script hay que ayudarle un poco :
* crear el siguiente enlace (ln -s /usr/local/lexmark/unix_prt_drivers /usr/lexprint)
* luego en el directorio bin, realizar los siguientes enlaces:
#ln -s /usr/local/lexmark/unix_prt_drivers/bin/.scripts/chqueue.sh chqueue
#ln -s /usr/local/lexmark/unix_prt_drivers/bin/.scripts/ckdevice.sh ckdevice
#ln -s /usr/local/lexmark/unix_prt_drivers/bin/.scripts/lsdevice.sh lsdevice
#ln -s /usr/local/lexmark/unix_prt_drivers/bin/.scripts/lsqueue.sh lsqueue
6. Si decidieron crear un menu para gnome (este lo creo cuando se ejecuta el script setup.lexprint) entonces solo deben de dar click en la opcion Aplicaciones->Herramientas del sistema->Lexmark Print Drivers y listo debe inciar la aplicacion y indicar donde se encuentra la impresora (en red o conectada localmente)
NOTA: si indican al script que cree el menu para kde dara un error dado que no encontraran los archivos para hacerlo, pueden modificar el script setup.lexprint o sencillamente pueden hacerlo manualmente he indicar que el comando que deben llamar es /usr/lexprint/bin/lexprint

-Otra solucion mas elegante es editar los archivo setup.lexprint y LEXPrtDrv.link indicando las opciones anteriores y crear un paquete para el slackware.. pero bueno eso lo pruebo despues... por ahora ya me funciona la impresora :)