Excelente, gracias.

2015-01-21 14:01 GMT-06:00 jvenegasperu . <jvenegasp...@gmail.com>:

> Hola Arturo
>
> puedes hacerte de estos libros te sorprendera todo lo que se puede lograr
> con postgres
>
>
> http://www.amazon.com/PostgreSQL-Admin-Cookbook-Simon-Riggs/dp/1849510288#reader_1849510288
>
> http://www.amazon.com/PostgreSQL-9-High-Availability-Cookbook/dp/1849516960/ref=sr_1_7?s=books&ie=UTF8&qid=1421870303&sr=1-7&keywords=postgresql#reader_1849516960
>
> saludos
>
>
>
> El 21 de enero de 2015, 12:33, Arturo Espinosa <artur...@gmail.com>
> escribió:
>
> Hola amigos. Soy Arturo Espinosa, de México.
>>
>> Primeramente, me gustaría recibir recomendaciones de su parte de libros,
>> en inglés o español, para aprender SQL y de preferencia con Postgres. Yo sé
>> algo de SQL, pero cuando las cosas se complican sólo un poco, empiezo a
>> flaquear.
>>
>> En segunda instancia, tengo una duda de SQL sobre Postgres, espero que me
>> puedan ayudar. He encontrado una solución a mi problema, pero no sé si hay
>> alguna manera más elegante de resolverlo. El mensaje se alarga un poco a
>> partir de aquí, pero he querido incluirles todo el material necesario para
>> que se les facilite emitir su opinión, que agradezco mucho.
>>
>> En una parte de una base de datos que estoy desarrollando tengo tres
>> relaciones para representar personas con fotografía. Cada persona puede
>> tener una cantidad variable de fotografías, y cada fotografía es un archivo
>> que tiene asociado una fecha de creación. Aquí las partes relevantes de la
>> estructura (he omitido enumeraciones, secuencias y foreign key constraints):
>>
>> CREATE TABLE public.persona (
>>                 persona_id INTEGER NOT NULL DEFAULT
>> nextval('public.persona_persona_id_seq'),
>>                 inst_id INTEGER NOT NULL,
>>                 type imr_persona_type NOT NULL,
>>                 prefix VARCHAR,
>>                 name VARCHAR NOT NULL,
>>                 paterno VARCHAR,
>>                 materno VARCHAR,
>>                 gender imr_gender,
>>                 remarks VARCHAR,
>>                 p_status imr_record_status NOT NULL,
>>                 CONSTRAINT persona_pk PRIMARY KEY (persona_id, inst_id)
>> );
>>
>> CREATE TABLE public.persona_photo (
>>                 persona_id INTEGER NOT NULL,
>>                 file_id INTEGER NOT NULL,
>>                 inst_id INTEGER NOT NULL,
>>                 CONSTRAINT persona_photo_pk PRIMARY KEY (persona_id,
>> file_id, inst_id)
>> );
>>
>> CREATE TABLE public.file (
>>                 file_id INTEGER NOT NULL DEFAULT
>> nextval('public.file_file_id_seq'),
>>                 inst_id INTEGER NOT NULL,
>>                 fname VARCHAR NOT NULL,
>>                 created TIMESTAMP NOT NULL,
>>                 mime_type_id INTEGER NOT NULL,
>>                 CONSTRAINT file_pk PRIMARY KEY (file_id, inst_id)
>> );
>>
>> CREATE TABLE public.account (
>>                 persona_id INTEGER NOT NULL,
>>                 inst_id INTEGER NOT NULL,
>>                 username VARCHAR(20) NOT NULL,
>>                 passwd VARCHAR(32) NOT NULL,
>>                 account_type imr_account_type NOT NULL,
>>                 status charp_account_status NOT NULL,
>>                 CONSTRAINT account_pk PRIMARY KEY (persona_id, inst_id)
>> );
>>
>> account es un subtipo de persona (relación uno-a-cero-o-uno).
>>
>> Ahora, tengo un stored procedure para listar a los usuarios del sistema.
>> La idea es que de entre los resultados se reporte el nombre del archivo de
>> su fotografía (file.fname). Como cada persona puede tener varias
>> fotografías asociadas, se toma la de más reciente creación. También, he
>> usado un LEFT JOIN para que el campo "picture" de un usuario dado sea NULL
>> en caso de que no tenga ninguna fotografía asociada.
>>
>> Aquí el query que preparé interactivamente con psql antes de meterlo en
>> el resto de mi stored procedure:
>>
>> SELECT
>>     persona_id,
>>     inst_id,
>>     fname
>> FROM
>>     (SELECT
>>         persona_id,
>>         inst_id,
>>         MAX(created)
>>     FROM
>>         persona_photo
>>         NATURAL JOIN file
>>     GROUP BY
>>         inst_id,
>>         persona_id
>>     ) AS q
>>     NATURAL JOIN file;
>>
>> Aquí el código de mi stored procedure:
>>
>> --- Dado un usurio del sistema identificado por _uid, obtener la lista de
>> usuarios pertenecientes a su instancia cuyo
>> --- status no sea DELETED. Se devuelven el id del usuario, tipo de
>> cuenta, username, nombre opcional del archivo que
>> --- representa su fotografía más reciente, anotaciones y datos personales.
>>
>> CREATE FUNCTION rp_user_list_get(_uid charp_user_id)
>>   RETURNS TABLE( persona_id integer, type imr_account_type, username
>> varchar, picture varchar, remarks varchar,
>>                           prefix varchar, name varchar, paterno varchar,
>> materno varchar, status charp_account_status,
>>                           gender imr_gender ) AS
>> $BODY$
>>
>> SELECT a.persona_id, a.account_type, a.username, f.fname, p.remarks,
>>        p.prefix, p.name, p.paterno, p.materno, a.status, p.gender
>>        FROM account AS a1
>>             JOIN account AS a USING (inst_id)
>>             JOIN persona AS p ON (a.persona_id = p.persona_id)
>>             LEFT JOIN (SELECT persona_id, inst_id, fname
>>                               FROM (SELECT persona_id, inst_id,
>> max(created)
>>                                            FROM persona_photo
>>                                                 NATURAL JOIN file
>>                                            GROUP BY inst_id, persona_id)
>> AS q
>>                                    NATURAL JOIN file) AS f
>>                       ON (a.inst_id = f.inst_id AND a.persona_id =
>> f.persona_id)
>>        WHERE a1.persona_id = $1 AND a.status <> 'DELETED';
>>
>> $BODY$
>>   LANGUAGE sql STABLE;
>>
>> charp_user_id es un domain a tipo integer simplemente. El argumento _uid
>> que recibe la función es el account_id del usuario que está pidiendo la
>> lista de usuarios desde el frontend. La base de datos está diseñada para
>> soportar varias instancias del negocio a nivel de datos (algo muy típico de
>> plataformas SaaS), por lo que se usa la llave foránea inst_id en todas las
>> tablas para identificar a las instancias (hay una relación "inst" que no he
>> incluido aquí por brevedad).
>>
>> La parte que no me gusta son los dos subqueries anidados para poder
>> extraer la fotografía más reciente, y que en el subquery 'q' haga yo un
>> natural join con file, para luego hacer otro en el subquery  'f'.
>>
>> Alguna sugerencia? Es este un buen query, o hay algo más eficiente o que
>> exprese más claramente lo que se desea obtener?
>>
>> Como me gustarí un recetario de SQL para aprender las mejores prácticas
>> para ciertos tipos de casos; si tienen recomendaciones de lecturas
>> parecidas, se las agradeceré.
>>
>> Saludos,
>> Arturo
>>
>>
>>
>>
>>
>
>
> --
> José Mercedes Venegas Acevedo
> cel claro 940180540
>
> mails: jvenegasp...@gmail.com
>

Responder a