SQL - script - subqueries

From Ibbddunq

(Difference between revisions)
Line 15: Line 15:
     (select diaFn, horaFn from formaParte where nomActo = 'osos'
     (select diaFn, horaFn from formaParte where nomActo = 'osos'
     union
     union
-
     select diaFn, horaFn from formaParte where nomActo = 'leones')
+
     select diaFn, horaFn from formaParte where nomActo = 'leones') ososOLeones
   order by diaFn, horaFn;
   order by diaFn, horaFn;
Line 24: Line 24:
     (select diaFn, horaFn, sum(duracion) duracionFuncion
     (select diaFn, horaFn, sum(duracion) duracionFuncion
     from formaParte
     from formaParte
-
     group by diaFn, horaFn) as duracionPorFuncion);
+
     group by diaFn, horaFn) as duracionPorFuncion) as duracionPorFuncion;
 +
== Subqueries en el WHERE ==
 +
 +
=== Tabla de 1x1 en comparaciones ===
 +
Si quiero el cachet más alto que tiene un artista no necesito nada de subqueries
 +
  select max(cachet) from artista;
 +
... si quiero el (o los) artista/s de máximo cachet, ahí sí
 +
  select nomArt, cachet
 +
  from artista
 +
  where cachet = (select max(cachet) from artista);
 +
(o una opción con subquery en el FROM)
 +
  select nomArt, cachet
 +
  from artista
 +
    natural join (select max(cachet) cachet from artista) as maxCachet;
 +
 +
Otra: quiero las ciudades de Córdoba con más población que cualquier ciudad de San Juan
 +
  select nomCiudad
 +
  from ciudad
 +
  where provincia = 'Cordoba'
 +
  and poblacion > (select max(poblacion) from ciudad where provincia = 'San Juan');
 +
 +
 +
=== IN / NOT IN ===
 +
 +
Con estos simulamos intersecciones y uniones, en algunos casos sencillos pero que cubren un montón.
 +
 +
Vamos con una: ciudades en las que se hicieron funciones en 2008 y en 2009. Haciendo un join moñito sale
 +
  select distinct f2008.nomCiudad
 +
  from funcion f2008
 +
      join funcion f2009 on f2008.nomCiudad = f2009.nomCiudad
 +
  where year(f2008.diaFn) = 2008 and year(f2009.diaFn) = 2009;
 +
pero también sale con
 +
# una intersección: ciudades de funciones 2008 inters. ciudades de funciones 2009; que también se puede expresar como
 +
# las ciudades 2008 que estén en el conjunto de ciudades 2009.
 +
De la forma 1 no se puede decir en SQL, de la forma 2 sí.
 +
  select distinct nomCiudad
 +
  from funcion
 +
  where year(diaFn) = 2008
 +
  and nomCiudad in (select nomCiudad from funcion where year(diaFn) = 2009);
 +
 +
 +
=== NOT EXISTS ===
 +
 +
 +
 +
== Para pensar ==
 +
Algunos queries que pueden iluminar
 +
* Artistas que viven en trailers de exactamente 4 ocupantes.
 +
* Idem: actos de las funciones con exactamente cuatro actos.
 +
*
 +
 +
== Resumen ==
Repaso de situaciones donde puede ser útil
Repaso de situaciones donde puede ser útil
* en el FROM
* en el FROM
** UNION ordenado
** UNION ordenado
 +
** JOIN con UNION
 +
** funciones de agrupación sobre grupos (la función más larga)
** cuando quiero hacer un join con una tabla agrupada
** cuando quiero hacer un join con una tabla agrupada
* tabla de 1x1 en comparaciones en el WHERE
* tabla de 1x1 en comparaciones en el WHERE
* IN con tabla de 1 atributo
* IN con tabla de 1 atributo
* NOT EXISTS vs NOT IN, queries correlacionados
* NOT EXISTS vs NOT IN, queries correlacionados

Revision as of 01:45, 28 April 2009

Contents

Concepto

Básicamente es lo que ya saben de AR: puedo hacer jugar el resultado de una consulta en otra, combinando operaciones.

Muchas veces se hace innecesario por la sintaxis básica de la sentencia SELECT de SQL, que permite hacer muchos joins, una selección (que se optimiza, entonces es como si fueran varias) y una proyección todo en una sola sentencia, y además lo del nombre compuesto de atributo evita la necesidad de renombrado.

Por otro lado, aparecen casos en donde la técnica de meter una consulta adentro de otra es muy útil. Veamos algunos.


Subqueries en el FROM

Una fácil: UNION ordenado, p.ej. quiero las funciones donde aparecen osos o leones ordenadas por fecha.

 select *
 from
   (select diaFn, horaFn from formaParte where nomActo = 'osos'
    union
    select diaFn, horaFn from formaParte where nomActo = 'leones') ososOLeones
 order by diaFn, horaFn;

Si quiero usar funciones agrupadas sobre grupos, entonces mi tabla es la de grupos

 -- la duracion de la funcion mas larga
 select max(duracionFuncion)
 from
   (select diaFn, horaFn, sum(duracion) duracionFuncion
    from formaParte
    group by diaFn, horaFn) as duracionPorFuncion) as duracionPorFuncion;


Subqueries en el WHERE

Tabla de 1x1 en comparaciones

Si quiero el cachet más alto que tiene un artista no necesito nada de subqueries

 select max(cachet) from artista;

... si quiero el (o los) artista/s de máximo cachet, ahí sí

 select nomArt, cachet
 from artista
 where cachet = (select max(cachet) from artista);

(o una opción con subquery en el FROM)

 select nomArt, cachet
 from artista
   natural join (select max(cachet) cachet from artista) as maxCachet;

Otra: quiero las ciudades de Córdoba con más población que cualquier ciudad de San Juan

 select nomCiudad
 from ciudad
 where provincia = 'Cordoba'
 and poblacion > (select max(poblacion) from ciudad where provincia = 'San Juan');


IN / NOT IN

Con estos simulamos intersecciones y uniones, en algunos casos sencillos pero que cubren un montón.

Vamos con una: ciudades en las que se hicieron funciones en 2008 y en 2009. Haciendo un join moñito sale

 select distinct f2008.nomCiudad
 from funcion f2008
     join funcion f2009 on f2008.nomCiudad = f2009.nomCiudad
 where year(f2008.diaFn) = 2008 and year(f2009.diaFn) = 2009;

pero también sale con

  1. una intersección: ciudades de funciones 2008 inters. ciudades de funciones 2009; que también se puede expresar como
  2. las ciudades 2008 que estén en el conjunto de ciudades 2009.

De la forma 1 no se puede decir en SQL, de la forma 2 sí.

 select distinct nomCiudad
 from funcion
 where year(diaFn) = 2008
 and nomCiudad in (select nomCiudad from funcion where year(diaFn) = 2009);


NOT EXISTS

Para pensar

Algunos queries que pueden iluminar

  • Artistas que viven en trailers de exactamente 4 ocupantes.
  • Idem: actos de las funciones con exactamente cuatro actos.

Resumen

Repaso de situaciones donde puede ser útil

  • en el FROM
    • UNION ordenado
    • JOIN con UNION
    • funciones de agrupación sobre grupos (la función más larga)
    • cuando quiero hacer un join con una tabla agrupada
  • tabla de 1x1 en comparaciones en el WHERE
  • IN con tabla de 1 atributo
  • NOT EXISTS vs NOT IN, queries correlacionados
Personal tools