sql with as 递归的实现(树形结构)

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

猜你喜欢

转载自blog.csdn.net/liufeifeinanfeng/article/details/83006713