Correlated Subqueries 相关子查询

本文深入讲解了Oracle数据库中相关子查询的应用场景与执行过程。通过具体案例,如筛选薪资高于部门平均水平的员工、查找多次变动工作的员工等,展示了相关子查询的实用性和灵活性。此外,还介绍了使用EXISTS操作符来简化查询逻辑的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

计算过程:

1.扫描外查询的第一条记录

2.扫描子查询,并将第一条记录的对应值传给子查询,由此计算出子查询的结果

3.根据子查询的结果,返回外查询的结果。

4.重复上述动作,开始扫描外查询的第二条记录,第三条记录,直至全部扫描完毕

--Correlated Subqueries 相关子查询
--当子查询引用了父语句中的表的列时,Oracle执行一个相关子查询。
--要把相关子查询的执行过程背下来
--查询雇员,条件是挣得钱比他所在部门的平均薪水要高
select last_name,salary,department_id
  from employees e
  where salary > (select avg(salary)
                    from employees
                    where department_id= e.department_id);
 
--查询至少换过两次工作的雇员
select last_name,salary
  from employees e
  where 2 <= (select count(*)
                 from job_history
                 where employee_id = e.employee_id);
--编写相关子查询,经常用到exists操作符
--该操作符用来判断子查询的结果集是否不为空,如果不为空,
--则返回true,否则返回false
--查询所有是经理的雇员
select employee_id,last_name,job_id
  from employees e
  where exists (select 'x'
                  from employees
                  where manager_id = e.employee_id);
--注意,以上子查询的select列表中的'x'是什么?
--它就是一个字面量x。因为exists操作符不关心子查询返回的列
--具体是什么(换句话说,它不使用子查询的返回值),它只关心
--子查询的结果集是否为空。因此,写上字面量,使得Oracle
--不需要计算返回的列值,可以提高一点点效率。
--通常写x还麻烦,直接写1就完了
select employee_id,last_name,job_id
  from employees e
  where exists (select 1
                  from employees
                  where manager_id = e.employee_id);
--查询所有的没有任何雇员的部门
select department_id,department_name
  from departments d
  where not exists (select 1
                      from employees
                      where department_id = d.department_id);
--相关更新:在update语句中子查询是相关子查询
create table empl6
  as select * from employees;
 
--给empl6表添加一个列
alter table empl6
  add (department_name varchar2(20));
 
--要求根据每个雇员的部门编号,将部门名称列的值填好
update empl6 e
  set department_name=(select department_name
                         from departments
                         where department_id= e.department_id);
--相关删除:在delete语句中子查询是相关子查询
--假设empl6表是在职员工表,emp_history表是已经离职的
--雇员表。要求从empl6表中删除所有已经的离职的雇员
delete from empl6 e
  where employee_id=(select empid
                       from emp_history
                       where empid=e.employee_id);
 



在 SQLAlchemy 中,子查询可以通过 `subquery()` 方法实现,该方法允许将一个查询作为另一个查询的条件来源。子查询通常用于嵌套查询结构中,例如 `WHERE`、`JOIN` 或 `SELECT` 子句中的嵌套查询。以下是几种常见的子查询实现方法: ### 使用 `subquery()` 创建子查询 可以通过 `query()` 创建一个查询对象,并调用 `subquery()` 方法将其转换为子查询对象。子查询的结果可以通过 `.c` 属性访问其列。 ```python from sqlalchemy.orm import Session from sqlalchemy import create_engine, func from models import User # 假设 User 是已定义的模型 engine = create_engine('sqlite:///example.db') session = Session(bind=engine) # 创建子查询 subq = session.query(User.city.label('city'), User.age.label('age')).filter(User.username == 'saber').subquery() # 使用子查询结果过滤主查询 users = session.query(User).filter(User.city == subq.c.city, User.age == subq.c.age) print(users.all()) ``` ### 在 `WHERE` 子句中使用子查询 子查询可以用于 `WHERE` 条件中,例如查找不在子查询结果中的记录。 ```python from models import Sales, GSCM_po # 创建子查询 subquery = session.query(GSCM_po.po).subquery() # 使用子查询过滤主查询 items = session.query(Sales).filter( Sales.invoice_no == None, Sales.cust_rcv_date != today, Sales.billing_po.not_in(subquery) ).all() ``` ### 在 `SELECT` 子句中使用子查询 子查询也可以作为标量值嵌入到 `SELECT` 子句中。 ```python from models import Group, Server # 创建子查询 subqry = session.query(func.count(Server.id).label("sid")).filter(Server.id == Group.id).correlate(Group).as_scalar() # 使用子查询作为 SELECT 子句的一部分 result = session.query(Group.name, subqry).all() ``` ### 在 `JOIN` 中使用子查询 子查询可以与主查询进行连接,例如使用 `outerjoin()`。 ```python from sqlalchemy.orm import aliased # 创建子查询 subq = session.query(User.city.label('city'), User.age.label('age')).filter(User.username == 'saber').subquery() # 创建别名 subq_alias = aliased(subq) # 使用 outerjoin 连接主查询和子查询 users = session.query(User).outerjoin(subq_alias, User.city == subq_alias.c.city) print(users.all()) ``` ### 在分组和过滤中使用子查询 结合 `group_by()` 和 `having()`,可以在分组后使用子查询进行过滤。 ```python from sqlalchemy import select, func from models import users, orders # 使用 SQLAlchemy Core 进行分组和分组后过滤 stmt = select([users.c.id, func.sum(orders.c.amount).label('total_amount')]) \ .select_from(users.join(orders)) \ .group_by(users.c.id) \ .having(func.sum(orders.c.amount) > 1000) # 执行查询 result = engine.execute(stmt).fetchall() ``` ### 相关问题 1. 如何在 SQLAlchemy 中使用子查询进行左连接? 2. 如何在 SQLAlchemy 中将子查询结果作为标量值? 3. 如何在 SQLAlchemy 中结合 `group_by()` 和子查询进行过滤? 4. 如何在 SQLAlchemy 中使用 `correlate()` 方法优化子查询性能? 5. 如何在 SQLAlchemy 中嵌套多个子查询? [^1] [^2] [^3] [^4]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值