SqlServer技巧:使用APPLY替代游标解决逐行运算问题

--数据准备
--表值函数 dbo.SplitString:按照分隔符将文本转换为表
declare @str1 varchar(max)
set @str1 = '7,8,9'
SELECT * FROM dbo.SplitString(@str1,',',1)

--示例:某表有Col1,Col2两列,想将Col2中的文本拆分为多行,并在拆分后保留Col1和Col2的对应关系
CREATE TABLE #TMP(
NAME VARCHAR(100) NULL,
STRING VARCHAR(MAX) NULL
)
TRUNCATE TABLE #TMP
INSERT INTO #TMP(NAME, STRING)
VALUES('TEST111','2,3,4'),
('TEST222','6,7'),
('TEST222',null)

使用情形:

  1. 想将某表关联表值函数返回的表

例如:某表有Col1,Col2两列,想将Col2中的文本拆分为多行,并在拆分后保留Col1Col2的对应关系

–方法1:使用游标,逐行拆分后拼接(略)
–方法2:使用APPLY进行逐行运算

--根据某列一行变多行,并保留其他列的对应关系
SELECT C.NAME, A.Value
FROM #TMP C
CROSS APPLY dbo.SplitString(C.STRING,',',1) A --去除NULL列

SELECT C.NAME, A.Value
FROM #TMP C
OUTER APPLY dbo.SplitString(C.STRING,',',1) A --保留NULL列
  1. 两表关联每个客户的前三笔交易,并展示客户信息

–方法1:用JOIN + ROW_NUMBER()
–方法2:用APPLY + TOP

--每个客户的前三笔交易
--方法1:用ROW_NUMBER()
SELECT C.custid, C.companyname, A.orderid, A.orderdate
FROM Sales.Customers C
LEFT JOIN(
SELECT ROW_NUMBER()OVER(PARTITION BY custid ORDER BY orderdate DESC, orderid DESC) AS RN
, custid, orderid, empid, orderdate, requireddate
FROM Sales.Orders
) A ON C.custid=A.custid
WHERE A.RN <=3
ORDER BY custid, RN

--方法2:用APPLY + TOP
SELECT C.custid, C.companyname, A.orderid, A.orderdate
FROM Sales.Customers C
CROSS APPLY(
SELECT TOP 3 orderid, empid, orderdate, requireddate
FROM Sales.Orders O
WHERE O.custid=C.custid
ORDER BY orderdate DESC, orderid DESC) A
ORDER BY C.custid

SQLServer基础:Apply关键字用法介绍

1、概念介绍

APPLY关键字是SQLServer版本中开始提供的一个系统关键字。

APPLY的功能同联接很类似,APPLY运算分左右两个部分,

APPLY的右表达式:左表达式的每一行都和右表达式进行一次计算,即右表达式需要根据左表达式提供的值进行相关计算来获取相关结果,然后返回给客户端。

APPLY的右表达式:是一个子查询或表值函数。

2、APPLY运算符和联接查询区别

APPLY:先进行左表达式的数据获取,然后根据左表达式的记录依次对右表达式的值进行相关获取。

联接:先对左右两张表进行笛卡尔乘积运算。

3、APPLY运算符的语法格式

CROSS APPLY:内部联接,两张表直接连接,不需要任何的关联条件,产生的结果就是这两张表的笛卡儿集等价于CROSS JOIN;

CROSS ApplyCROSS JOIN的区别:Cross Apply 可以在关联表子查询中用前一个关联表的字段的值,CROSS JOIN不可以。

比如:

SELECT * FROM t1 a CROSS APPLY t2 b WHERE a.id=b.id 
--相当于 inner join 
SELECT * FROM t1 a CROSS JOIN t2 b WHERE a.id=b.id --报错

OUTER APPLY:左外联接,右侧的表表达式返回一个空集合,CROSS APPLY运算符不会返回相应的左侧行,即OUTER APPLY和在派生表上进行LEFT JOIN是等同的

SELECT * FROM t1 a OUTER APPLY (select * from t2 where id=a.id) b 
-- 相当于 left join。

4、Cross Apply 用途

4.1 配合表值函数使用

如果查询结果集需要用到表值函数对某个字段的值进行处理的话,可以使用CROSS APPLY

4.2 top子查询的用法

– 查询语文第一名,数学前两名,英语前五名的name,学科,分数,用cross apply实现方法如下

SELECT b.* FROM (
select Subject='Chiness',num=1 
union all
select 'Math',3 union all
select 'English',5
)a cross apply (select top(a.num) * from Students 
where Subject=a.Subject )b
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值