subconsulta postgresql
Introducción a las subconsultas
La subconsulta se refiere a una
declaración de consulta anidada en otras declaraciones SELECT, INSERT, UPDATE y DELETE
. La función de una subconsulta es algo similar a una consulta de unión de varias tablas y también se utiliza para devolver o filtrar datos de varias tablas relacionadas. Por
ejemplo, queremos saber qué empleados tienen un salario mensual mayor que el salario mensual promedio, lo cual se puede lograr mediante una subconsulta.
select e.first_name, e.last_name, e.salary
from employees e
where salary > (select avg(salary) from employees);
La subconsulta debe colocarse entre paréntesis, también denominada consulta interna, y la declaración de consulta que contiene la subconsulta se denomina consulta externa. Además de la
cláusula WHERE, las subconsultas también se pueden utilizar en otras cláusulas, como listas SELECT, cláusulas FROM, etc.
tabla derivada
La subconsulta en la cláusula FROM se denomina tabla derivada (tabla derivada)
SELECT column1, column2, ...
FROM (subquery) AS table_alias;
La subconsulta equivale a crear una tabla temporal alias_tabla
-- 获取每个部门的总月薪
select d.department_name,
ds.sum_salary
from departments d
join (select department_id,
sum(salary) as sum_salary
from employees
group by department_id) ds
on (d.department_id = ds.department_id);
La subconsulta devuelve el número de departamento y el salario mensual total del departamento, luego se realiza la consulta de conexión con la tabla de departamentos.
operador EN
Si la subconsulta WHERE devuelve varios registros, puede utilizar el operador IN para el filtrado condicional:
-- in
-- 存在 2008 年 01 月 01 日以后入职员工的部门
select *
from cps.public.departments d
where d.department_id in
(
select distinct e.department_id
from cps.public.employees e
where e.hire_date >= date '2008-01-01'
);
TODO operador
El operador TODO se utiliza con operadores de comparación para comparar un valor con la lista devuelta por una subconsulta:
-- all
-- 返回了月薪比销售部门(department_id = 80)所有员工都高的员工
select e.first_name ,
e.salary
from cps.public.employees e
where e.salary > all
(select e2.salary from cps.public.employees e2 where e2.department_id= 80);
El sql anterior es equivalente al siguiente sql
-- all
-- 返回了月薪比销售部门(department_id = 80)所有员工都高的员工
select e.first_name ,
e.salary
from cps.public.employees e
where e.salary >
(select max(e2.salary) from cps.public.employees e2 where e2.department_id= 80);
CUALQUIER operador
El operador ANY es similar al operador ALL, pero tiene efectos diferentes:
-- any
-- 返回了月薪比销售部门(department_id = 80)任何一个员工都高的员工
select e.first_name ,
e.salary
from cps.public.employees e
where e.salary >
(select min(e2.salary) from cps.public.employees e2 where e2.department_id= 80);
El sql anterior es equivalente al siguiente sql
-- any
-- 返回了月薪比销售部门(department_id = 80)任何一个员工都高的员工
select e.first_name ,
e.salary
from cps.public.employees e
where e.salary > any
(select e2.salary from cps.public.employees e2 where e2.department_id= 80);
Además, ALGUNOS y CUALQUIER son sinónimos. El efecto de algunos es el mismo que cualquier
Subconsulta correlacionada
Existe otro tipo de subconsulta que hace referencia a columnas de la consulta externa y, por tanto, está relacionada con la consulta externa: se denominan subconsultas correlacionadas.
/*
* 子查询中使用了外查询的字段(e.department_id)。对于外部查询中的每个员工,
* 运行子查询返回他/她所在部门的平均月薪,然后传递给外部查询进行判断
* */
-- 返回月薪大于所在部门平均月薪的员工
select
e.first_name,
e.salary
from cps.public.employees e
where e.salary >
(select avg(e2.salary) from cps.public.employees e2 where e2.department_id = e.department_id);
Las subconsultas correlacionadas se ejecutan una vez para cada fila de la consulta externa (la base de datos puede optimizar esto), mientras que las
subconsultas no correlacionadas se ejecutan solo una vez para toda la ejecución de la consulta.
subconsulta horizontal
En términos generales, las subconsultas solo pueden hacer referencia a campos en la consulta externa y no pueden usar campos en otras tablas en la misma jerarquía. Por ejemplo:
/**/
select
d.department_name ,t.sum_sal
from cps.public.departments d
join (
select sum(e.salary) sum_sal from cps.public.employees e where e.department_id = d.department_id
) t on true;
La declaración anterior se refiere a los campos de la tabla de departamentos a la izquierda en JOIN, lo que genera un error de sintaxis. Para hacer esto, necesitamos
usar una subconsulta LATERAL. Al agregar la palabra clave LATERAL, la subconsulta puede hacer referencia
a columnas en la tabla de la izquierda:
/*
* 每个部门的名称和总月薪
* */
select
d.department_name ,t.sum_sal
from cps.public.departments d
cross join lateral (
select sum(e.salary) sum_sal from cps.public.employees e where e.department_id = d.department_id
) t;
operador EXISTE
El operador EXISTS se utiliza para comprobar la existencia de resultados de subconsulta. EXISTS devuelve Verdadero si la subconsulta devuelve algún resultado;
en caso contrario, Falso
-- EXISTS
select *
from cps.public.departments d
where exists
(select 1 from cps.public.employees e
where e.department_id = d.department_id
and e.hire_date > date '2008-01-01'
);
-- not exists不存在
select *
from cps.public.departments d
where not exists
(select 1 from cps.public.employees e
where e.department_id = d.department_id
and e.hire_date > date '2008-01-01'
);
[NOT] IN se usa para verificar si un valor pertenece a la lista de resultados de una subconsulta (=). [NOT] EXISTS solo verifica la existencia del resultado de la subconsulta . NOT EXISTS se evalúa como Verdadero si NULL está presente en el resultado de la subconsulta; sin embargo, NOT IN se evalúa
como Falso porque el resultado de NOT (X = NULL) es NULL
-- in 在什么取值范围内
select *
from cps.public.departments d
where d.department_id in
(select distinct e.department_id from cps.public.employees e)
-- not in 不属于子查询结果列
select *
from cps.public.departments d
where d.department_id not in
(select distinct e.department_id from cps.public.employees e)