<left_table>  {cross|outer} apply <right_table>

它是先得出右表里的数据,然后把此数据一条一条的放入左表表式中,分别得出结果集,最后把结果集整合到一起就是最终的返回结果集了

详解:(拆分后的数据 ,像for循环一样 ,一条一条的进入到left表中, 然后返回一个集合 ,最后把所有的集合整合到一块  就是最终的结果


字面理解:

apply,应用,当左边语句完成后,则执行右边

outer apply,外围应用,当左边语句完成后,则执行右边,且是外围应用,对本身不影响

cross apply,交叉应用,当左边语句完成后,则执行右边,且右边要是没有数据,则左边也不显示


其他理解:

  • 使用上跟inner join 和 left join 有点像,但是实现不一样,apply更灵活,例如可以调用自定义函数,join则性能更好
  • cross apply跟outer apply区别,就像 inner join 和 left join的区别
  • 还有一个语法叫cross join , 区别是,cross join 不能将左边的参数传到右边,所以理论上说,是废弃掉的



示例:

USE tempdb
GO
IF OBJECT_ID('stu') IS NOT NULL
DROP TABLE stu
GO
CREATE TABLE stu(
	stuId INT PRIMARY KEY,
	stuName NVARCHAR(5) NOT NULL	
)
GO
IF OBJECT_ID('score') IS NOT NULL
DROP TABLE score
GO
CREATE TABLE score(
	scoreId INT IDENTITY(1,1) PRIMARY KEY,
	stuId INT NOT NULL,
	course NVARCHAR(5) NOT NULL,
	score INT NOT NULL	
)
GO
SET NOCOUNT ON
INSERT INTO stu(stuId, stuName) VALUES (1,'小明')
INSERT INTO stu(stuId, stuName) VALUES (2,'小华')
INSERT INTO stu(stuId, stuName) VALUES (3,'小江')
 
INSERT INTO score (stuId,course,score) VALUES (1,'语文',90)
INSERT INTO score (stuId,course,score) VALUES (1,'数学',88)
INSERT INTO score (stuId,course,score) VALUES (1,'英语',96)
INSERT INTO score (stuId,course,score) VALUES (2,'语文',80)
GO
 
--统计出所有学生的 他本人所有成绩之中的 最高分, 没有成绩也要显示
SELECT * 
FROM stu 
	OUTER APPLY (
		SELECT TOP 1 * FROM score WHERE stu.stuId=score.stuId ORDER BY score DESC 
	) AS ff
/*
stuId       stuName scoreId     stuId       course score
----------- ------- ----------- ----------- ------ -----------
1           小明      3           1           英语     96
2           小华      4           2           语文     80
3           小江      NULL        NULL        NULL   NULL
*/
 
--统计出所有学生的 他本人所有成绩之中的 最高分, 没有成绩不要显示
SELECT * 
FROM stu 
	CROSS APPLY (
		SELECT TOP 1 * FROM score WHERE stu.stuId=score.stuId ORDER BY score DESC 
	) AS ff
 
/*
stuId       stuName scoreId     stuId       course score
----------- ------- ----------- ----------- ------ -----------
1           小明      3           1           英语     96
2           小华      4           2           语文     80
*/
 
 
/*
--CROSS APPLY 用于函数的范例
--string_split 只能用于 SQL Server 2016+
SELECT * FROM stu CROSS APPLY string_split( stuff(stu.stuName,2,0,'.'),'.') AS ff
stuId       stuName value
----------- ------- ------
1           小明      小
1           小明      明
2           小华      小
2           小华      华
3           小江      小
3           小江      江
*/




参考:  

https://blog.csdn.net/yenange/article/details/91125451

https://www.cnblogs.com/MirZhai/p/15269963.html