WITH AS短语,也叫做子查询部分(subquery factoring),定义一个sql 片段,改sql 片段会被整个sql语句用到。其中最实用的功能就是数据的递归,递归的原理:递归包括至少两个查询,一个查询作为递归的基点也就是起点,另一个查询作为递归的成员。
一、定义一个公司(company)表 ,总公司下面包含子公司,子公司下面又包含分办事处
CREATE TABLE [dbo].[Company](
[id] [nvarchar](50) NOT NULL, //Id 主键
[companyName] [nvarchar](50) NULL, //公司名称
[pId] [nvarchar](50) NULL //父节点id
) ON [PRIMARY]
二、 插入数据到公司表
insert into Company(id,companyName,pid)values('A','A总公司','/') //总公司
insert into Company(id,companyName,pid)values('B','B分公司01','A') //分公司
insert into Company(id,companyName,pid)values('C','C分公司02','A') //分公司
insert into Company(id,companyName,pid)values('B1','B办事处','B') //办事处
insert into Company(id,companyName,pid)values('B2','B办事处','B') //办事处
insert into Company(id,companyName,pid)values('B3','B办事处','B') //办事处
insert into Company(id,companyName,pid)values('C1','C办事处','C') //办事处
insert into Company(id,companyName,pid)values('C2','C办事处','C') //办事处
insert into Company(id,companyName,pid)values('C3','C办事处','C') //办事处
<!-- 查找所有当前节点的所有子节点 > 查找B分公司和下面的办事处
with temp as(
select * from company where pid='B'
union all
select c.* from company c ,temp t where c.pid=t.id)
select * from temp
<!--查询当前节点的所有父节点 > 查找ID 为B3的 办事处 上层管理机构
with t as(
select * from company where id ='B3'
union all
select c.* from t ,company c where t.pid=c.id
)
select * from t
<!--删除当前节点和所有子节点> 删除B 分公司和以下的办事处
with temp as (
select * from company where id='B'
union all
select c.* from company c, temp t where c.pid=t.id
) delete from company where id in(select id from temp)
经典案例
现在要求计算每个月的返利金额,规则如下:
1月份销售金额大于任务额 返利额=金额*返利点
2月份销售金额大于任务额 返利额=(金额-1月份返利额)*返利点
3月份销售金额大于任务额 返利额=(金额-1,2月份返利额)*返利点
以后月份依次类推,销售额小于任务额时,返利为0
CREATE TABLE [dbo].[tb](
[qj] [int] NULL, -- 月份,本测试假设从1月份开始,并且数据都是连续的月份,中间没有隔断
[je] [int] NULL,-- 本月销售实际金额
[rwe] [int] NULL,-- 本月销售任务额
[fld] [float] NULL-- 本月金额大于任务额时的返利点,返利额为je*fld
) ON [PRIMARY]
sql 语句
with t as(
select * , case when je > rwe then (je*fld) else 0 end fle,cast(0 as float) tmp from tb where qj='1'
union all
select tb.* ,case when tb.je > tb.rwe then (tb.je-t.fle-t.tmp)*tb.fld else 0 end fle,t.fle+t.tmp tmp from tb ,t where tb.qj=t.qj+1
) select * from t