[Pgsql-ayuda] consulta select complejo

Alejandro Diego Garin linuxero2@yahoo.com
Fri, 22 Feb 2002 09:17:17 -0300


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=EDdo tu
> problema en los archivos del Web, por esto te respondo al privado, creo
> que te puedo ayudar si todav=EDa tienes la necesidad:
>
> resumir=E9 lo que pueda, tu lo llevas a los nombres correctos, etc.
>
> tu tabla maestra, para este ejercicio, tiene:
>    serv_id, serv_nombre     llam=E9mosle  (1)
>
> en otras relaciones tenemos:
>   serv_id, mem_id         llam=E9mosle  (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=E9mosle  (=
0)
> para cada serv_id ya sea que tenga o no tenga disco o mem.
>
> ***** soluci=F3n ****
> bi=E9n, tu ya hiciste la mitad que qued=F3 m=E1s o menos as=ED:
>
> "(2)  left join  (4)  using(mem_id)"  con lo que se obtuvo:
>   serv_id, mem_id, mem_cap      llam=E9mosle  (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=F3n 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=E9ntesis y la asignaci=F3n de alias para cada
> selectx (es necesario para usar los select en la cl=E1usula FROM)
> los nombres para estos alias son de tu elecci=F3n
> el "order by" es optativo, por supuesto.
> he usado un peque=F1o modelo as=ED que est=E1 probado que funciona.
> ES NECESARIO realizar este =FAltimo join FUERA de los select a fin de n=
o
> duplicar las entradas de mem_cap o disco_cap, lo cual ocurre
> inevitablemente si tratas de meter m=E1s join en el mismo y =FAnico sel=
ect
> original. Por tanto creo que es la =FAnica salida o al menos la mejor c=
on
> join's.
>
> Tratando de reescribir tu propio select debes llegar a algo as=ED 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 lo=
s
> 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 US=
ING
> (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=E9n, eso es todo, no sab=EDa mucho de JOINs pero ahora s=E9 mucho m=E1=
s.  :-))
> as=ED aprendemos, no s=F3lo meti=E9ndole tiempo a nuestros problemas si=
no
> tanbi=E9n a los de los dem=E1s.
> mientras investigu=E9 tu necesidad aprend=ED mucho m=E1s que s=F3lo de =
JOINs .
> as=ED que muchas GRACIAS  :-))
>
> Un Saludo fraterno....
>    John.
>
> PD: si te fu=E9 =FAtil puedes mandarlo a la lista, ya que el problema q=
ued=F3
> planteado all=ED, podr=EDa servir a otros.
> bye.
>
>
> Alejandro Diego Garin linuxero2@yahoo.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 est=
e
> 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 a=
un
> 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 l=
a
> 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=F3:
> > > 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 U=
SING
> > > (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=E1 este query sea m=E1s sencillo (suponiendo que las tablas que
> > mencionas donde est=E1n los tipos de discos duros y su capacidad tien=
en
> > tambi=E9n sus id's), resumo a continuaci=F3n mi suposici=F3n:
> >
> > 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 =3D mem.mem_id
> > and   ser.hdd_id =3D hdd_id
> > group by ser.ser_id
> > order by ser.ser_id
> >
> >
> > saludos