¿Las subconsultas agregan potencia expresiva a las consultas SQL?

29

¿SQL necesita subconsultas?

Imagine una implementación suficientemente generalizada del lenguaje de consulta estructurado para bases de datos de relaciones. Como la estructura de la SELECTdeclaración canónica de SQL es bastante importante para que esto tenga sentido, no apelo directamente al álgebra relacional, pero podría enmarcar esto en esos términos haciendo restricciones apropiadas en la forma de las expresiones.

Un SQL SELECTconsulta generalmente consiste en un saliente (la SELECTparte) cierto número de JOINoperaciones (la JOINparte), cierto número de SELECTION operaciones (en SQL, las WHEREcláusulas), y a continuación, establecer en cuanto a las operaciones ( UNION, EXCEPT, INTERSECT, etc.), seguido de otro Consulta SQL SELECT.

Las tablas que se unen pueden ser los resultados calculados de expresiones; en otras palabras, podemos tener una declaración como:

SELECT t1.name, t2.address
  FROM table1 AS t1 
  JOIN (SELECT id, address 
          FROM table2 AS t3 
         WHERE t3.id = t1.id) AS t2
 WHERE t1.salary > 50,000;

Nos referiremos al uso de una tabla calculada como parte de una consulta SQL como subconsulta. En el ejemplo anterior, el segundo (sangrado) SELECTes una subconsulta.

¿Se pueden escribir todas las consultas SQL de tal manera que no se utilicen subconsultas? El ejemplo anterior puede:

SELECT t1.name, t2.address
  FROM table1 AS t1 
  JOIN table2 AS t2
    ON t1.id = t2.id
 WHERE t1.salary > 50,000;

Este ejemplo es algo espurio o trivial, pero uno puede imaginar casos en los que se podría requerir un esfuerzo considerablemente mayor para recuperar una expresión equivalente. En otras palabras, ¿es el caso de que para cada consulta SQL con subconsultas, exista una consulta q ' sin subconsultas de modo que q y q ' tengan garantizados los mismos resultados para las mismas tablas subyacentes? Limitemos las consultas SQL a la siguiente forma:qqqq

SELECT <attribute>,
      ...,
      <attribute>
 FROM <a table, not a subquery>
 JOIN <a table, not a subquery>
  ...
 JOIN <a table, not a subquery>
WHERE <condition>
  AND <condition>
  ...
  AND <condition>

UNION
 -or-
EXCEPT
 -or-
<similar>

SELECT ...

Y así. Creo que las uniones externas izquierda y derecha no agregan mucho, pero si me equivoco, no dudes en señalarlo ... en cualquier caso, también son un juego justo. En cuanto a las operaciones de configuración, supongo que cualquiera de ellos está bien ... unión, diferencia, diferencia simétrica, intersección, etc. todo lo que sea útil. ¿Hay alguna forma conocida a la que se puedan reducir todas las consultas SQL? ¿Alguno de estos elimina las subconsultas? ¿O hay algunos casos en los que no existe una consulta equivalente libre de subconsultas? Se agradecen las referencias ... o una demostración (por prueba) de que son o no necesarias sería fantástico. Gracias, y lo siento si este es un resultado celebrado (o trivial) del cual soy dolorosamente ignorante.

Patrick87
fuente
55
Mi instinto me dice que siempre puedes unir todo y seleccionar desde allí siempre que no necesites valores agregados. Seleccionar todas las entradas con un valor mayor que el promedio de su columna parece requerir calcular primero el promedio, por lo tanto, se necesita una subconsulta.
Raphael
@Raphael Estoy bastante seguro de que incluso puede hacer valores agregados, solo necesita hacer más autouniones y agrupaciones (haciéndolo exponencialmente más grande, pero aún posible). Sin embargo, no estoy seguro de cómo probaría formalmente que puedes hacer todo de esa manera.
Kevin
@Kevin ¿Está seguro de que la cantidad de operaciones necesarias no depende de la cantidad de filas? Porque no podemos tener eso, ¿verdad?
Raphael
1
El ejemplo normales que tengo para requerir una subconsulta está contando duplicados: select count(*) from (select id from sometable group by id having count(*)>1) d. Porque incluye group byno he puesto esto como respuesta.
Mark Hurd
Por cierto AFAIK en SQL normal, la ONcláusula es necesaria para JOINs, aunque se obtiene un producto cruzado con solo una coma.
Mark Hurd

Respuestas:

9

Hay cierta confusión terminológica; el bloque de consulta entre paréntesis

SELECT t1.name, t2.address
  FROM table1 
  JOIN (SELECT id, address 
          FROM table2 AS t3 
         WHERE t3.id = t1.id) 

se llama vista interior . Una subconsulta es un bloque de consulta dentro de la cláusula WHERE o SELECT, por ejemplo

select deptno from dept
where 3 < (select count(1) from emp 
           where dept.deptno=emp.deptno)

En cualquier caso, la vista interna o la subconsulta se pueden desagrupar en "plano" project-restrict-join. Subconsulta correlacionada con agregación innecesaria en vistas internas con agrupación, que luego innecesaria en consulta plana.

select deptno from dept d
    where 3 < (select avg(sal) from emp e
               where d.deptno=e.deptno)

select d.deptno from dept d, ( 
    select deptno from emp e
    group by deptno
    having avg(sal) > 3
) where d.deptno=e.deptno

select d.deptno from dept d, emp e
where d.deptno=e.deptno 
group by d.deptno
having avg(sal) > 3

En cuanto a las reglas algebraicas para la optimización de consultas, se sabe que el álgebra relacional se axiomatiza en una red relacional que simplifica las transformaciones de consultas como se demuestra aquí y allá .

Tegiri Nenashi
fuente
Tengo curiosidad ¿Puede agregar un ejemplo de una consulta que use algunos campos promedio, por ejemplo, seleccionando todas las entradas con un valor superior al promedio? No me queda claro cómo se vería eso después de aplanar.
Raphael
16

Para traducir su declaración al álgebra relacional, creo que pregunta:

σA(A)σB(B)σA(σB(AB))

σ

La respuesta es "Sí", y es una optimización de consulta estándar. Para ser honesto, no estoy seguro de cómo probar esto de una manera que no implique preguntas: es solo una propiedad de selección y unión. Puede argumentar inductivamente para agregar la cantidad de capas de consultas anidadas que desee.

Además, puede preguntar:

ABC(AB)(CD)

Nuevamente, la respuesta es sí, porque la unión es asociativa. Se pueden hacer declaraciones similares sobre la proyección también.

Un tipo notable de "subconsulta" que creo que no puede ser "aplanado" es with. Una forma de ver esto es observar que si tiene una withdeclaración, puede tener una función recursiva, que no se puede escribir sin usar subconsultas.

Para resumir: en el caso específico que mencionó, no, SQL no necesita subconsultas, y puede probarlo inductivamente. Sin embargo, en general, hay características que requieren subconsultas.

Xodarap
fuente
El comportamiento recursivo withse introdujo en SQL: 1999 y hace que el lenguaje resultante sea estrictamente más expresivo.
András Salamon
1

"¿Las subconsultas agregan potencia expresiva a las consultas SQL?"

Lo hicieron, al menos antes de la introducción de EXCEPT en el lenguaje SQL.

Antes de la introducción de EXCEPT, no había forma de expresar una diferencia relacional o semidiferencia en SQL sin recurrir a subconsultas.

En estos días, todos los operadores primitivos "típicos" de "el" álgebra relacional pueden expresarse sin subconsultas:

Reunión natural puede hacerse a través NATURAL JOIN, o unirse EN
UNION se puede hacer a través de Unión
MENOS se puede hacer a través SALVO
DEL PROYECTO / renombrar / Extender se puede hacer throug SELECT
RESTRICT se puede hacer a través DONDE
literales relacionales se puede hacer a través de valores
transitivos cierres pueden hacerse de forma recursiva CON

Erwin Smout
fuente