Presentacion - Subconsultas

32
SUBCONSULTAS CARLOS ALFONSO BASTO OLAYA

description

Subconsultas BD

Transcript of Presentacion - Subconsultas

Subconsultas

SubconsultasCarlos Alfonso Basto OlayaQu es?Es un comando SELECT dentro de otro comando SELECT.

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

Una subconsulta esta anidad en una consulta externa, de hecho una subconsulta puede contener otras subconsultas hasta una profundidad considerable. Las subconsultas siempre deben aparecer entre parntesis.VentajasPermiten consultas estructuradas de forma que es posible aislar cada parte de un comando.Proporcionan un modo alternativo de realizar operaciones que de otro modo necesitaran JOINs y UNIONs complejos.Son, en la opinin de mucha gente, lebles. De hecho, fue la innovacin de las subconsultas lo que dio a la gente la idea original de llamar a SQL Structured Query Language.caractersticasSubconsultaescalarregistrocolumnatablaDISTINCT, GROUP BY, ORDER BY, LIMIT, JOINs, trucos de ndices, UNION, comentarios, funciones, y as.RestriccionesUna restriccin es que el comando exterior de una subconsulta debe ser: SELECT, INSERT, UPDATE, DELETE, SET, o DO.Otra restriccin es que actualmente no puede modificar una tabla y seleccionar de la misma tabla en la subconsulta. Esto se aplica a comandos tales como DELETE, INSERT, REPLACE, y UPDATE. Subconsulta como valores escalaresCREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);INSERT INTO t1 VALUES(100, 'abcde');SELECT (SELECT s2 FROM t1);

Hay contextos en donde una subconsulta literal no se puede usar, por ejemplo si un comando permite un valor literal (LIMIT, LOAD DATA).Subconsultas en consultasoperando_no_subconsulta operador_comparador (subconsulta)

He aqu un ejemplo de una comparacin comn de subconsultas que no puede hacerse mediante un JOIN. Encuentra todos los valores en la tabla t1 que son iguales a un valor mximo en la tabla t2:

SELECT column1 FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2);Encuentra todos los registros en la tabla t1 que contengan un valor que ocurre dos veces en una columna dada:

SELECT * FROM t1 AS tWHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);

Subconsulta de registros (ms adelante).Subconsultas con ANY, IN y SOMEoperando operador_comparador ANY (subconsulta)operando IN (subconsulta)operando operador_comparador SOME (subconsulta)ANY significa return TRUE si la comparacin es TRUE para ANY (cualquiera) de los valores en la columna que retorna la subconsulta.

SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

TRUE = Alguna (1 o ms) de las comparaciones es verdaderaFALSE = Ninguna de las comparaciones es verdaderaUNKNOWN = Si la tabla de la subconsulta tiene todos sus registros en NULL

SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);SELECT s1 FROM t1 WHERE s1 IN (SELECT s1 FROM t2); # NOT IN es diferente a ANYSELECT s1 FROM t1 WHERE s1 = SOME (SELECT s1 FROM t2);

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2); # Por qu mostrara error?Subconsultas con ALLoperando operador_comparador ALL(subconsulta)

TRUE = Todas las comparaciones son verdaderasTRUE = Si la tabla de la subconsulta est vacaFALSE = Alguna (1 o ms) de las comparaciones son falsasUNKNOWN = Alguna (1 o ms) de las comparaciones es con NULLTRUESELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);

UNKNOWNSELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);

UNKNOWNSELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);

SELECT s1 FROM t1 WHERE s1 ALL (SELECT s1 FROM t2);SELECT s1 FROM t1 WHERE s1 NOT IN (SELECT s1 FROM t2);Subconsultas de registroSELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

(1,2), ROW(1,2) -> constructores de registros

SELECT * FROM t1 WHERE (column1,column2) = (1,1);SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;SELECT column1,column2,column3FROM t1WHERE (column1,column2,column3) IN(SELECT column1,column2,column3 FROM t2);EXISTS y NOT EXISTSSi la subconsulta contiene registros, as sea solo valores NULL

EXISTS (subconsulta) => TRUENOT EXISTS (subconsulta) => FALSEQu clase de tienda hay en una o ms ciudades?

SELECT DISTINCT store_type FROM StoresWHERE EXISTS (SELECT * FROM Cities_StoresWHERE Cities_Stores.store_type = Stores.store_type);

Qu clase de tienda no hay en ninguna ciudad?

SELECT DISTINCT store_type FROM StoresWHERE NOT EXISTS (SELECT * FROM Cities_StoresWHERE Cities_Stores.store_type = Stores.store_type);Subconsultas correlacionadasUna subconsulta correlacionada es una subconsulta que contiene una referencia a una tabla que tambin aparece en la consulta exterior.

SELECT * FROM t1 WHERE column1 = ANY(SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

MySQL evalua desde dentro hacia fuera

SELECT column1 FROM t1 AS xWHERE x.column1 = (SELECT column1 FROM t2 AS xWHERE x.column1 = (SELECT column1 FROM t3WHERE x.column2 = t3.column1));

Reescribir la consulta como un JOIN puede mejorar el rendimiento.Las subconsultas correlacionadas no pueden referirse a los resultados de funciones agregadas de la consulta exterior.Subconsultas en la clusula FROMSELECT ... FROM (subconsulta) [AS] name ...

[AS] name es obligatoria

CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);INSERT INTO t1 VALUES (1,'1',1.0);INSERT INTO t1 VALUES (2,'2',2.0);SELECT sb1,sb2,sb3FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sbWHERE sb1 > 1;

Resultado: 2, '2', 4.0.Suponga que quiere conocer la media de un conjunto de sumas para una tabla agrupada.

SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;# No funciona

SELECT AVG(sum_column1)FROM (SELECT SUM(column1) AS sum_column1FROM t1 GROUP BY column1) AS t1;# FuncionaLas subconsultas en la clusula FROM pueden retornar un escalar, columna, registro o tabla, pero no pueden ser subconsultas correladas.

UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1); # ErrorErrores en SubconsultasNmero incorrecto de columnas de la subconsulta:

ERROR 1241 (ER_OPERAND_COL)SQLSTATE = 21000Message = "Operand should contain 1 column(s)

SELECT (SELECT column1, column2 FROM t2) FROM t1;Nmero incorrecto de registros de la subconsulta:

ERROR 1242 (ER_SUBSELECT_NO_1_ROW)SQLSTATE = 21000Message = "Subquery returns more than 1 row

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);Tabla usada incorrectamente en la subconsulta:

Error 1093 (ER_UPDATE_TABLE_USED)SQLSTATE = HY000Message = "You can't specify target table 'x'for update in FROM clause

UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);

Motores transaccionales -> Falla el comando enteroMotores no transaccionales -> Modificaciones antes del error se preservanOptimizar subconsultasUsar clusulas de subconsulta que afecten al nmero u orden de los registros en la subconsulta.

SELECT * FROM t1 WHERE t1.column1 IN(SELECT column1 FROM t2 ORDER BY column1);SELECT * FROM t1 WHERE t1.column1 IN(SELECT DISTINCT column1 FROM t2);SELECT * FROM t1 WHERE EXISTS(SELECT * FROM t2 LIMIT 1);Un JOIN por una subconsulta:

SELECT DISTINCT t1.column1 FROM t1, t2WHERE t1.column1 = t2.column1;

SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (SELECT column1 FROM t2);Mueva las clusulas desde fuera hacia dentro en la subconsulta.

SELECT * FROM t1WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);

SELECT * FROM t1WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);

SELECT (SELECT column1 FROM t1) + 5 FROM t2;

SELECT (SELECT column1 + 5 FROM t1) FROM t2;Use una subconsulta de registro en lugar de una subconsulta correlacionada.

SELECT * FROM t1WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1AND t2.column2=t1.column2);

SELECT * FROM t1WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);Use NOT (a = ANY (...)) en lugar de a ALL (...).Use x = ANY (table containing (1,2)) en lugar de x=1 OR x=2.Use = ANY en lugar de EXISTS.Para subconsultas no correlacionadas que siempre retornan un registro, IN siempre es ms lento que =.Algunas optimizaciones que hace MySQL:

MySQL ejecuta subconsultas no correlacionadas slo una vez. Use EXPLAIN para asegurar que una subconsulta dada realmente no est correlacionada.MySQL reescribe subconsultas IN, ALL, ANY, y SOME para aprovechar que las columnas de la lista de SELECT de la subconsulta est indexada.MySQL reemplaza subconsultas de la siguiente forma con una funcin de bsqueda de ndice, que EXPLAIN describe como tipo especial de join (unique_subquery o index_subquery):... IN (SELECT indexed_column FROM single_table ...)MySQL mejora expresiones de la siguiente forma con una expresin que involucre MIN() o MAX(), a no ser que hayan involucrados valores NULL o conjuntos vacos:WHERE 5 > ALL (SELECT x FROM t);WHERE 5 > (SELECT MAX(x) FROM t);Gracias