java apply 例子,现实生活中的例子,何时在SQL中使用OUTER / CROSS APPLY

本文详细介绍了SQL中CROSS APPLY和OUTER APPLY的使用,特别是在处理INNER JOIN和LEFT JOIN时的特殊情况。CROSS APPLY用于在结果集中保留所有外部表的记录,而在JOIN函数中无法实现此效果。OUTER APPLY则在CROSS APPLY的基础上进一步确保了LEFT JOIN的功能,即使内部查询返回NULL值,也会保留外部表的记录。文中通过实例展示了如何在查询中使用这两个操作符来获取期望的结果,包括选取每个ID的最后两个日期记录以及与函数结合使用的情况。

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

在各种情况下,您无法避免 CROSS APPLY 或 OUTER APPLY .

考虑你有两张 table .

MASTER TABLE

x------x--------------------x

| Id | Name |

x------x--------------------x

| 1 | A |

| 2 | B |

| 3 | C |

x------x--------------------x

DETAILS TABLE

x------x--------------------x-------x

| Id | PERIOD | QTY |

x------x--------------------x-------x

| 1 | 2014-01-13 | 10 |

| 1 | 2014-01-11 | 15 |

| 1 | 2014-01-12 | 20 |

| 2 | 2014-01-06 | 30 |

| 2 | 2014-01-08 | 40 |

x------x--------------------x-------x

交叉申请

在很多情况下我们需要用 CROSS APPLY 替换 INNER JOIN .

1. If we want to join 2 tables on TOP n results with INNER JOIN functionality

考虑是否需要从 Master 中选择 Id 和 Name ,并从 Details table 中为每个 Id 选择最后两个日期 .

SELECT M.ID,M.NAME,D.PERIOD,D.QTY

FROM MASTER M

INNER JOIN

(

SELECT TOP 2 ID, PERIOD,QTY

FROM DETAILS D

ORDER BY CAST(PERIOD AS DATE)DESC

)D

ON M.ID=D.ID

以上查询生成以下结果 .

x------x---------x--------------x-------x

| Id | Name | PERIOD | QTY |

x------x---------x--------------x-------x

| 1 | A | 2014-01-13 | 10 |

| 1 | A | 2014-01-12 | 20 |

x------x---------x--------------x-------x

看,它生成最后两个日期的结果,最后两个日期是 Id ,然后仅在 Id 的外部查询中加入这些记录,这是错误的 . 为此,我们需要使用 CROSS APPLY .

SELECT M.ID,M.NAME,D.PERIOD,D.QTY

FROM MASTER M

CROSS APPLY

(

SELECT TOP 2 ID, PERIOD,QTY

FROM DETAILS D

WHERE M.ID=D.ID

ORDER BY CAST(PERIOD AS DATE)DESC

)D

并形成他的结果 .

x------x---------x--------------x-------x

| Id | Name | PERIOD | QTY |

x------x---------x--------------x-------x

| 1 | A | 2014-01-13 | 10 |

| 1 | A | 2014-01-12 | 20 |

| 2 | B | 2014-01-08 | 40 |

| 2 | B | 2014-01-06 | 30 |

x------x---------x--------------x-------x

这是工作 . CROSS APPLY 中的查询可以引用外部表,其中 INNER JOIN 不能执行此操作(抛出编译错误) . 找到最后两个日期时,加入在 CROSS APPLY 内完成,即 WHERE M.ID=D.ID .

2. When we need INNER JOIN functionality using functions.

当我们需要从 Master 表和 function 获得结果时, CROSS APPLY 可以用作 INNER JOIN 的替代 .

SELECT M.ID,M.NAME,C.PERIOD,C.QTY

FROM MASTER M

CROSS APPLY dbo.FnGetQty(M.ID) C

这是功能

CREATE FUNCTION FnGetQty

(

@Id INT

)

RETURNS TABLE

AS

RETURN

(

SELECT ID,PERIOD,QTY

FROM DETAILS

WHERE ID=@Id

)

产生了以下结果

x------x---------x--------------x-------x

| Id | Name | PERIOD | QTY |

x------x---------x--------------x-------x

| 1 | A | 2014-01-13 | 10 |

| 1 | A | 2014-01-11 | 15 |

| 1 | A | 2014-01-12 | 20 |

| 2 | B | 2014-01-06 | 30 |

| 2 | B | 2014-01-08 | 40 |

x------x---------x--------------x-------x

外部申请

1. If we want to join 2 tables on TOP n results with LEFT JOIN functionality

考虑我们是否需要从 Master 中选择Id和Name,并从 Details 表中为每个Id选择最后两个日期 .

SELECT M.ID,M.NAME,D.PERIOD,D.QTY

FROM MASTER M

LEFT JOIN

(

SELECT TOP 2 ID, PERIOD,QTY

FROM DETAILS D

ORDER BY CAST(PERIOD AS DATE)DESC

)D

ON M.ID=D.ID

形成以下结果

x------x---------x--------------x-------x

| Id | Name | PERIOD | QTY |

x------x---------x--------------x-------x

| 1 | A | 2014-01-13 | 10 |

| 1 | A | 2014-01-12 | 20 |

| 2 | B | NULL | NULL |

| 3 | C | NULL | NULL |

x------x---------x--------------x-------x

这将带来错误的结果,即,即使我们加入 Id ,它也只会带来 Details 表中最新的两个日期数据,而不管 Id . 所以正确的解决方案是使用 OUTER APPLY .

SELECT M.ID,M.NAME,D.PERIOD,D.QTY

FROM MASTER M

OUTER APPLY

(

SELECT TOP 2 ID, PERIOD,QTY

FROM DETAILS D

WHERE M.ID=D.ID

ORDER BY CAST(PERIOD AS DATE)DESC

)D

形成以下所需结果

x------x---------x--------------x-------x

| Id | Name | PERIOD | QTY |

x------x---------x--------------x-------x

| 1 | A | 2014-01-13 | 10 |

| 1 | A | 2014-01-12 | 20 |

| 2 | B | 2014-01-08 | 40 |

| 2 | B | 2014-01-06 | 30 |

| 3 | C | NULL | NULL |

x------x---------x--------------x-------x

2. When we need LEFT JOIN functionality using functions.

当我们需要从 Master 表和 function 获取结果时, OUTER APPLY 可以用作 LEFT JOIN 的替代 .

SELECT M.ID,M.NAME,C.PERIOD,C.QTY

FROM MASTER M

OUTER APPLY dbo.FnGetQty(M.ID) C

功能就在这里 .

CREATE FUNCTION FnGetQty

(

@Id INT

)

RETURNS TABLE

AS

RETURN

(

SELECT ID,PERIOD,QTY

FROM DETAILS

WHERE ID=@Id

)

产生了以下结果

x------x---------x--------------x-------x

| Id | Name | PERIOD | QTY |

x------x---------x--------------x-------x

| 1 | A | 2014-01-13 | 10 |

| 1 | A | 2014-01-11 | 15 |

| 1 | A | 2014-01-12 | 20 |

| 2 | B | 2014-01-06 | 30 |

| 2 | B | 2014-01-08 | 40 |

| 3 | C | NULL | NULL |

x------x---------x--------------x-------x

CROSS APPLY和OUTER APPLY的共同特征

CROSS APPLY 或 OUTER APPLY 可用于在解锁时保留 NULL 值,这些值是可互换的 .

考虑一下你有下表

x------x-------------x--------------x

| Id | FROMDATE | TODATE |

x------x-------------x--------------x

| 1 | 2014-01-11 | 2014-01-13 |

| 1 | 2014-02-23 | 2014-02-27 |

| 2 | 2014-05-06 | 2014-05-30 |

| 3 | NULL | NULL |

x------x-------------x--------------x

当您使用 UNPIVOT 将 FROMDATE AND TODATE 带到一列时,它将默认消除 NULL 值 .

SELECT ID,DATES

FROM MYTABLE

UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P

产生以下结果 . 请注意,我们已经错过了 Id 的记录 3

x------x-------------x

| Id | DATES |

x------x-------------x

| 1 | 2014-01-11 |

| 1 | 2014-01-13 |

| 1 | 2014-02-23 |

| 1 | 2014-02-27 |

| 2 | 2014-05-06 |

| 2 | 2014-05-30 |

x------x-------------x

在这种情况下, CROSS APPLY 或 OUTER APPLY 将是有用的

SELECT DISTINCT ID,DATES

FROM MYTABLE

OUTER APPLY(VALUES (FROMDATE),(TODATE))

COLUMNNAMES(DATES)

形成以下结果并保留 Id ,其值为 3

x------x-------------x

| Id | DATES |

x------x-------------x

| 1 | 2014-01-11 |

| 1 | 2014-01-13 |

| 1 | 2014-02-23 |

| 1 | 2014-02-27 |

| 2 | 2014-05-06 |

| 2 | 2014-05-30 |

| 3 | NULL |

x------x-------------x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值