Re: [Pgsql-ayuda] consulta select complejo

From: Alejandro Diego Garin <linuxero2(at)yahoo(dot)com>
To: pgsql-ayuda(at)tlali(dot)iztacala(dot)unam(dot)mx
Cc: John Nye Stowhas <jnye(at)udelmar(dot)cl>
Subject: Re: [Pgsql-ayuda] consulta select complejo
Date: 2002-02-22 12:17:17
Message-ID: 200202221217.JAA20366@smilodon.lan
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Gracias John, muy buena tu respueta! Incluyo una copia a la lista
ya que como dices tal vez pueda ser de utilidad para alguien mas.
Finalmente habia encontrado una solucion utilizando un razonamiento
similar al tuyo, la diferencia fue que para no complicar el select
cree dos vistas donde en una tenia la info de la memoria y en otra
sobre los discos y luego simplemente utilice un join entre ambas.

un gusto recibir tu mensaje. Salu2
Alejandro

On Wednesday 20 February 2002 16:23, you wrote:
> Alejandro, saludos, soy absolutamente nuevo en la lista y he leído tu
> problema en los archivos del Web, por esto te respondo al privado, creo
> que te puedo ayudar si todavía tienes la necesidad:
>
> resumiré lo que pueda, tu lo llevas a los nombres correctos, etc.
>
> tu tabla maestra, para este ejercicio, tiene:
> serv_id, serv_nombre llamémosle (1)
>
> en otras relaciones tenemos:
> serv_id, mem_id llamémosle (2)
> y
> serv_id, disco_id (3)
>
> las cuales se pueden alimentar de:
> mem_id, mem_cap (4)
> y
> disco_id, disco_cap (5)
>
> respectivamente.
>
> queremos obtener:
> serv_id, serv_nombre, sum(mem_cap), sum(disco_cap) llamémosle (0)
> para cada serv_id ya sea que tenga o no tenga disco o mem.
>
> ***** solución ****
> bién, tu ya hiciste la mitad que quedó más o menos así:
>
> "(2) left join (4) using(mem_id)" con lo que se obtuvo:
> serv_id, mem_id, mem_cap llamémosle (6)
>
> terminando con:
> "(1) left join (6) using(serv_id)" con lo que se obtuvo:
> serv_id, serv_nombre, mem_id, mem_cap (7)
>
> de la cual obtubiste los datos tomando:
> select serv_id, serv_nombre, sum(mem_cap)
> from (7)
> group by serv_id, serv_nombre
>
> reemplazando (7) y, a su vez, (6) para tener todo en función de (1)
> , (2) y (4) que son las tablas originales
> llegaste al select que planteas:
>
> select serv_id, serv_nombre, sum(mem_cap)
> from (1) left join ( (2) left join (4) using(mem_id) )
> using(serv_id)
> group by serv_id, serv_nombre
>
> ha este select llamemosle select1
>
> ****** LO QUE FALTA *******
> de la misma forma debes obtener el equivalente para la capacidad de
> disco, o sea:
>
> select serv_id, serv_nombre, sum(disco_cap)
> from (1) left join ( (3) left join (5) using(disco_id) )
> using(serv_id)
> group by serv_id, serv_nombre
>
> ha este select llamemosle select2
>
> bien, ahora select1 entrega cada servidor id con su nombre y su ram
> total (cada servidor sin repetir ni omitir)
> y select2 entrega cada servidor id con su nombre y su HDD total (cada
> servidor sin repetir ni omitir)
>
> luego select1 y select2 entregan la misma cantidad de registros con
> serv_id, serv_nombre COMUNES.
>
> entonces SOLO FALTA UN JOIN ENTRE AMBOS
> y tienes:
>
> select * from (select1) as S1 left join (select2) as S2
> using(serv_id, serv_nombre) order by serv_id
>
> no debes olvidar los paréntesis y la asignación de alias para cada
> selectx (es necesario para usar los select en la cláusula FROM)
> los nombres para estos alias son de tu elección
> el "order by" es optativo, por supuesto.
> he usado un pequeño modelo así que está probado que funciona.
> ES NECESARIO realizar este último join FUERA de los select a fin de no
> duplicar las entradas de mem_cap o disco_cap, lo cual ocurre
> inevitablemente si tratas de meter más join en el mismo y único select
> original. Por tanto creo que es la única salida o al menos la mejor con
> join's.
>
> Tratando de reescribir tu propio select debes llegar a algo así como:
> (suponiendo que tu tabla de discos se llama "disk" y el campo de
> capacidad en GB se llama "disk_capacity" y la tabla de relacion con los
> servers se llama "servers_disk" con el campo disk_id en ambas tablas
> para identificar el disco)
>
> SELECT * FROM
> (SELECT ser.ser_id, trim(ser.ser_hostname) as ser_hostname,
> sum(mem.mem_capacity) as MBytes
> FROM servers AS ser LEFT JOIN ( servers_memory LEFT JOIN memory AS mem
> USING (mem_id) ) USING (ser_id)
> GROUP BY ser.ser_id, ser.ser_hostname) AS S1
> LEFT JOIN
> (SELECT ser.ser_id, trim(ser.ser_hostname) as ser_hostname,
> sum(disco.disk_capacity) as discoGB
> FROM servers AS ser LEFT JOIN ( servers_disk LEFT JOIN disk AS disco USING
> (disk_id) ) USING (ser_id)
> GROUP BY ser.ser_id, ser.ser_hostname) AS S2
> USING(ser.ser_id, ser.ser_hostname)
> ORDER BY ser.ser_id
>
>
> Bién, eso es todo, no sabía mucho de JOINs pero ahora sé mucho más. :-))
> así aprendemos, no sólo metiéndole tiempo a nuestros problemas sino
> tanbién a los de los demás.
> mientras investigué tu necesidad aprendí mucho más que sólo de JOINs .
> así que muchas GRACIAS :-))
>
> Un Saludo fraterno....
> John.
>
> PD: si te fué útil puedes mandarlo a la lista, ya que el problema quedó
> planteado allí, podría servir a otros.
> bye.
>
>
> Alejandro Diego Garin linuxero2(at)yahoo(dot)com <mailto:linuxero2%40yahoo.com>
> Fri, 8 Feb 2002 13:12:53 -0300
>
>
> ------------------------------------------------------------------------
>
> Gente:
> Una consulta:
>
> Tengo el siguiente select
>
> SELECT ser.ser_id, trim(ser.ser_hostname) as ser_hostname,
> sum(mem.mem_capacity) as MBytes
> FROM servers AS ser LEFT JOIN ( servers_memory JOIN memory AS mem USING
> (mem_id) ) USING (ser_id)
> GROUP BY ser.ser_id,ser.ser_hostname
>
> donde me despliega la cantidad de memoria que tiene un servidor, En este
> select se utilizan tres tablas. Servidores, Memorias (tipo y capac,) y
> servers_memory (almancena la relacion entre una y otra)
> Como hago para incluir otro set de 2 tablas donde tengo almacenado
> la capacidad de los discos del servidor?
> O sea:
>
> El select me retorna esto
> ser_id | ser_hostname | mbytes
> --------+--------------+--------
> 16 | aaa01 | 512
> 17 | aaa02 | 512
> 18 | aaa03 | 512
>
> y necesito que termine siendo asi
>
> ser_id | ser_hostname | mbytes | discoGB
> --------+--------------+---------------------
> 16 | aaa01 | 512 | 40
> 17 | aaa02 | 512 | 150
> 18 | aaa03 | 512 | 25
>
>
> Lo que no encontre es la sintaxis correcta para hacer los joins
> correspondientes para esa cantidad de tablas, alguna pista?
>
>
> Gracias

On Friday 08 February 2002 15:11, you wrote:
> Gracias por tu mail, pero las estructuras de las tablas no son asi. El tema
> es que la relacion entre memoria y servidores es 1 a muchos.
> Por un lado tenga la tabla memorias, donde tengo el tipo y la capacidad
> por otro lado la tabla servidores
> y por otro la relacion entre ambas.
> Un servidor puede tener x cantidad de tipos de memoria.
> Utilizo la sintaxis de "joins" ya que debo mostrar los servidores que aun
> no tienen relacion con un tipo de memoria, de la forma que tu me lo
> sugieres solo mostrarias los servidores que tienen el dato y eso por el
> momento no es necesariamente correcto.
> El tema es que se me complicaba cuando quiero unir en el mismo select
> dos tablas mas donde tengo los tpos de disco/capacidad y la tabla que la
> relaciona con los servidores :(
> No encontre un ejemplo de como hacer eso.
> Gracias por la resp.
>
> Esta es la estructura de las tablas, la misma idea aplica para discos
> duros.
>
> CREATE TABLE servers (
> ser_id INTEGER DEFAULT nextval('servers_seq'),
> ser_hostname char(35),
>
> UNIQUE(ser_hostname),
> PRIMARY KEY(ser_id)
> );
> CREATE TABLE memory (
> mem_id INTEGER DEFAULT nextval('memory_seq'),
> mem_type VARCHAR(50) NOT NULL,
> mem_capacity INTEGER NOT NULL,
> UNIQUE(mem_type,mem_capacity),
> PRIMARY KEY(mem_id)
> );
> CREATE TABLE servers_memory (
> sermem_id INTEGER DEFAULT nextval('servers_memory_seq'),
> ser_id INTEGER CONSTRAINT fk_server_memory_ser_id REFERENCES
> servers(ser_id)
> ON UPDATE CASCADE
> ON DELETE CASCADE,
> mem_id INTEGER CONSTRAINT fk_server_memory_cpu_id REFERENCES
> memory(mem_id)
> ON UPDATE CASCADE
> ON DELETE NO ACTION
> );
>
> On Wednesday 06 February 2002 13:37, you wrote:
> > El vie, 08-02-2002 a las 10:12, Alejandro Diego Garin escribió:
> > > Gente:
> > > Una consulta:
> > >
> > > Tengo el siguiente select
> > >
> > > SELECT ser.ser_id, trim(ser.ser_hostname) as ser_hostname,
> > > sum(mem.mem_capacity) as MBytes
> > > FROM servers AS ser LEFT JOIN ( servers_memory JOIN memory AS mem USING
> > > (mem_id) ) USING (ser_id)
> > > GROUP BY ser.ser_id,ser.ser_hostname
> > >
> > > Lo que no encontre es la sintaxis correcta para hacer los joins
> > > correspondientes para esa cantidad de tablas, alguna pista?
> > >
> > >
> > > Gracias
> >
> > quizá este query sea más sencillo (suponiendo que las tablas que
> > mencionas donde están los tipos de discos duros y su capacidad tienen
> > también sus id's), resumo a continuación mi suposición:
> >
> > servers
> > --------
> > ser_id
> > ser_hostname
> > mem_id
> > hdd_id
> >
> > memory
> > -------
> > mem_id
> > mem_name
> > mem_cap
> >
> > hdd
> > ------
> > hdd_id
> > hdd_name
> > hdd_capacity
> >
> > select ser.ser_id, trim(ser.ser_hostname) as ser_hostname,
> > mem.mem_cap, hdd.hdd_capacity
> > from servers as ser, memory as mem, hdd
> > where ser.mem_id = mem.mem_id
> > and ser.hdd_id = hdd_id
> > group by ser.ser_id
> > order by ser.ser_id
> >
> >
> > saludos

In response to

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Alejandro Rivadeneira 2002-02-24 20:26:09 [Pgsql-ayuda] Postgresql / informacion en Espanol
Previous Message Roberto Andrade Fonseca 2002-02-19 04:53:50 [Pgsql-ayuda] [Fwd: [HACKERS] Second decent PostgreSQL CBT released - Introduction to Referential Integrity]