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