在论坛中出现的比较难的sql问题:40(子查询 销售和历史库存)

 

最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。

 

所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。


 

求教:我有个表有入库时间,有出库时间,我想得到该样式号每月的销售和历史库存

http://bbs.csdn.net/topics/390629790

库结构大概是这样:
货号    样式号    入库时间    出库时间
a001    10    2011-1-10        
b002    10    2011-1-10    2011-2-1
c003    10    2012-1-15    2012-2-2
d004    10    2013-2-3    2013-1-5
e005    10    2013-2-3        
f006    15    2011-2-15    2011-3-16
g007    15    2011-2-16    2012-3-16
h009    15    2013-1-10    
m012    18    2011-1-4        
c009    18    2011-4-5    2012-5-6
f008    18    2012-2-19    2013-1-1
e008    18    2013-1-5    2013-2-6
 
我想得到的结果:
样式号    日期    销售件数    库存件数    
10    2011-2    1    1
10    2012-2    1    1
10    2013-1    1    2
15    2011-3    1    0
15    2012-3    1    1
18    2012-5    1    1
18    2013-1    1    1
18    2013-2    1    1


我的解法:

 

if object_id('tb') is not null
   drop table tb
go
 
create table tb 
(
[货号] varchar(20),[样式号] int,
[入库时间] datetime,
[出库时间] datetime
) 

insert into tb
SELECT 'a001',10,'2011-01-10',null UNION ALL
SELECT 'b002',10,'2011-01-10','2011-02-01' UNION ALL
SELECT 'c003',10,'2012-01-15','2012-02-02' UNION ALL
SELECT 'd004',10,'2013-01-03','2013-01-05' UNION ALL
SELECT 'e005',10,'2013-01-03',null UNION ALL
SELECT 'f006',15,'2011-02-15','2011-03-16' UNION ALL
SELECT 'g007',15,'2011-02-16','2012-03-16' UNION ALL
SELECT 'h009',15,'2013-01-10',null UNION ALL
SELECT 'm012',18,'2011-01-04',null UNION ALL
SELECT 'c009',18,'2011-04-05','2012-05-06' UNION ALL
SELECT 'f008',18,'2012-02-19','2013-01-01' UNION ALL
SELECT 'e008',18,'2013-01-05','2013-02-06'
go


;with t
as(
select *,
       row_number() over(partition by 样式号 
                             order by 入库时间,出库时间) as rownum
from tb
),

tt
as
(
select *,
       case when 出库时间 is null 
                 then (select top 1 出库时间 
                       from t t2 
                       where t1.样式号 = t2.样式号 and
                             t1.rownum > t2.rownum
                       order by t2.rownum desc)
            else 出库时间
       end as prior_row,
       
       case when 出库时间 is null 
                 then (select top 1 出库时间 
                       from t t2 
                       where t1.样式号 = t2.样式号 and
                             t1.rownum < t2.rownum
                       order by t2.rownum )
            else 出库时间
       end as next_row
       
from t t1
),

ttt
as
(
select 样式号,
       convert(varchar(7),isnull(next_row,prior_row),120) as 日期,
       count(出库时间) 销售件数,
       count(入库时间) 库存件数,
       count(入库时间) - count(出库时间) 剩余库存
       --row_number() over(partition by 样式号 
       --order by convert(varchar(7),isnull(next_row,prior_row),120)) as rownum
from tt
group by 样式号,
         convert(varchar(7),isnull(next_row,prior_row),120)

)

select t1.样式号,t1.日期,
       isnull(t1.销售件数,0) as 销售件数 ,
       
       isnull(t1.库存件数,0) + 
       isnull((select  sum(库存件数)-sum(销售件数) as 剩余库存 from ttt t2 
               where t2.样式号 = t1.样式号
                     and t2.日期 < t1.日期
               ),0) -
       isnull(t1.销售件数,0) as 库存件数
       
from ttt t1
order by t1.样式号 
/*
样式号	日期	    销售件数	库存件数
10	    2011-02	1	    1
10	    2012-02	1	    1
10	    2013-01	1	    2
15	    2011-03	1	    0
15	    2012-03	1	    1
18	    2012-05	1	    1
18	    2013-01	1	    1
18	    2013-02	1	    1
*/


转载于:https://www.cnblogs.com/momogua/p/8304464.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值