出库表:编号     日期           数量
----------------------------
001 2009-1-1       30
001 2009-1-15      -2
001 2009-1-18       -5
001 2009-2-1       15
001 2009-2-2      -10
001 2009-2-15     -2要求查询得出(查询截止日期2009-3-1),需要考虑先进先出:编号     库龄小于30天        库龄30-89天         库龄90天以上
-------------------------------------------------------------
001          15                 11                    0这样的sql语句怎样写?

解决方案 »

  1.   

    做日期函数datediff!就差不多了
    但不明白的是库龄分析跟先进先出有什么关系吗?
      

  2.   

    select 
      编号,
      库龄小于30天=sum(case when datediff(dd,日期,'2009-3-1')<30 then 数量 else 0 end),
      库龄小于库龄30-89天=sum(case when datediff(dd,日期,'2009-3-1') between 31 and 89 then 数量 else 0 end),
      库龄90天以上=sum(case when datediff(dd,日期,'2009-3-1')>90 then 数量 else 0 end)
    group by 
      编号
      

  3.   

    datediff(day,rq,getdate())<30
    datediff(day,rq,getdate())>=30 and datediff(day,rq,getdate())<=89
    datediff(day,rq,getdate())>=90
    分别对应小于30,30-89,超过90在WHERE中指定即可
      

  4.   

    --算出来不一样
    ----------------------------------------------------------------
    -- Author  :fredrickhu(我是小F,向高手学习)
    -- Date    :2009-08-31 16:11:20
    -- Verstion:
    --      Microsoft SQL Server 2005 - 9.00.4035.00 (Intel X86) 
    -- Nov 24 2008 13:01:59 
    -- Copyright (c) 1988-2005 Microsoft Corporation
    -- Developer Edition on Windows NT 5.2 (Build 3790: Service Pack 1)
    --
    ----------------------------------------------------------------
    --> 测试数据:[tb]
    if object_id('[tb]') is not null drop table [tb]
    go 
    create table [tb]([编号] varchar(3),[日期] datetime,[数量] int)
    insert [tb]
    select '001','2009-1-1',30 union all
    select '001','2009-1-15',-2 union all
    select '001','2009-1-18',-5 union all
    select '001','2009-2-1',15 union all
    select '001','2009-2-2',-10 union all
    select '001','2009-2-15',-2
    --------------开始查询--------------------------
    select 
      编号,
      库龄小于30天=sum(case when datediff(dd,日期,'2009-3-1')<30 then 数量 else 0 end),
      [库龄小于库龄30-89天]=sum(case when datediff(dd,日期,'2009-3-1') between 31 and 89 then 数量 else 0 end),
      库龄90天以上=sum(case when datediff(dd,日期,'2009-3-1')>90 then 数量 else 0 end)
    from 
      tb
    group by 
      编号----------------结果----------------------------
    /* 编号   库龄小于30天     库龄小于库龄30-89天 库龄90天以上
    ---- ----------- ------------ -----------
    001  3           23           0(1 行受影响)
    */
      

  5.   

    先MARK,自己写一下,测试后发上来
      

  6.   

    declare @t1 table( 编号 varchar(10), 日期 date , 数量 int)insert into @t1 values('001', '2009-1-1',       30 )
    insert into @t1 values('001', '2009-1-15',      -2 )
    insert into @t1 values('001', '2009-1-18',       -5 )
    insert into @t1 values('001', '2009-2-1',       15 )
    insert into @t1 values('001', '2009-2-2',     -10 )
    insert into @t1 values('001', '2009-2-15',    -2 )select  a.编号 ,
    SUM( case a.日期 when 0 then a.数量 else 0 end) as 库龄小于30天,
    SUM( case a.日期 when 1 then a.数量 else 0 end) as 库龄3089天 ,
    SUM( case a.日期 when 2 then a.数量 else 0 end) as 库龄90天以上
     from 
    (select 编号, 数量, case  when  DATEDIFF(day,日期,'2009-3-1') <30 then 0 
      when DATEDIFF(day,日期,'2009-3-1') between 30 and 89 then 1 
      else 2 end as 日期
      from @t1)a group by a.编号
      
      

  7.   


    declare @t1 table( 编号 varchar(10), 日期 date , 数量 int)insert into @t1 values('001', '2009-1-1',       30 )
    insert into @t1 values('001', '2009-1-15',      -2 )
    insert into @t1 values('001', '2009-1-18',       -5 )
    insert into @t1 values('001', '2009-2-1',       15 )
    insert into @t1 values('001', '2009-2-2',     -10 )
    insert into @t1 values('001', '2009-2-15',    -2 )select b.编号,
    case when b.[库龄90天以上]+b.[库龄3089天以上负]+b.库龄3089天以上正 + b.库龄小于30天负>=0 then b.库龄小于30天正
       else b.库龄小于30天正 + b.[库龄90天以上]+b.[库龄3089天以上负]+b.库龄3089天以上正 + b.库龄小于30天负
       end as '库龄小于30天', case when b.[库龄90天以上] + b.库龄3089天以上负 + b.库龄小于30天负 >=0 then b.库龄3089天以上正
          when b.[库龄90天以上] + b.库龄3089天以上负 + b.库龄小于30天负 + b.库龄3089天以上正 >=0 then 
               b.[库龄90天以上] + b.库龄3089天以上负 + b.库龄小于30天负 + b.库龄3089天以上正
               else 0
               end as '库龄3089天',
     b.[库龄90天以上]
     
     from(
    select
    a.编号,
    (select isnull(SUM(数量),0) from @t1 where 编号=a.编号 and 
     DATEDIFF(day,日期,'2009-3-1') >89) as '库龄90天以上',
    (select isnull(SUM(数量),0) from @t1 where 编号=a.编号 and 
     DATEDIFF(day,日期,'2009-3-1') between 30 and 89 and 数量>=0) as '库龄3089天以上正', 
    (select isnull(SUM(数量),0) from @t1 where 编号=a.编号 and 
     DATEDIFF(day,日期,'2009-3-1') between 30 and 89 and 数量<0) as '库龄3089天以上负',
     (select isnull(SUM(数量),0) from @t1 where 编号=a.编号 and 
     DATEDIFF(day,日期,'2009-3-1') <30 and 数量>=0) as '库龄小于30天正',
     (select isnull(SUM(数量),0) from @t1 where 编号=a.编号 and 
     DATEDIFF(day,日期,'2009-3-1') <30 and 数量<0) as '库龄小于30天负'
    from @t1 a group by a.编号)b  
      

  8.   

    ---测试数据---
    if object_id('[tb]') is not null drop table [tb]
    go
    create table [tb]([编号] varchar(3),[日期] datetime,[数量] int)
    insert [tb]
    select '001','2009-1-1',30 union all
    select '001','2009-1-15',-2 union all
    select '001','2009-1-18',-5 union all
    select '001','2009-2-1',15 union all
    select '001','2009-2-2',-10 union all
    select '001','2009-2-15',-2
     
    ---查询---
    select 
      a.编号,
      a.日期,
      a.入库数量,
      b.出库总量
    into #
    from
      (select 编号,日期,数量 as 入库数量 from tb where 数量>0) a
    left join
      (select 编号,sum(数量) as 出库总量 from tb where 数量<0 group by 编号) b
    on
      a.编号=b.编号select
      编号,
      [库龄小于30天]=sum(case when datediff(day,日期,'2009-3-1')<30 then 库存 else 0 end),    
      [库龄30-89天]=sum(case when datediff(day,日期,'2009-3-1') between 30 and 89 then 库存 else 0 end),  
      [库龄90天以上]=sum(case when datediff(day,日期,'2009-3-1')>=90 then 库存 else 0 end)
    from
    (
    select 
      编号,
      日期,
      库存=case when 库存<0 then 0 else case when 入库数量<库存 then 入库数量 else 库存 end end
    from
    (  
    select *,(select sum(入库数量) from # where 日期<=t.日期)+出库总量 as 库存 from # t
    ) t) tt
    group by
      编号drop table #---结果---
    编号   库龄小于30天     库龄30-89天    库龄90天以上     
    ---- ----------- ----------- ----------- 
    001  15          11          0(所影响的行数为 1 行)
      

  9.   


    if object_id('[tab]') is not null drop table [tb]
    go 
    create table [tab]([编号] varchar(3),[日期] datetime,[数量] int)
    insert [tab]
    select '001','2009-1-1',30 union all
    select '001','2009-1-15',-2 union all
    select '001','2009-1-18',-5 union all
    select '001','2009-2-1',15 union all
    select '001','2009-2-2',-10 union all
    select '001','2009-2-15',-2
    --select * from tab
    select [编号], sum(case when datediff(dd,[日期],'2009-03-01')<30 then [数量] else 0 end) as '30',
    sum(case when datediff(dd,[日期],'2009-03-01') between 30 and 89 then [数量] else 0 end) as '3089',
    sum(case when datediff(dd,[日期],'2009-03-01')>=90 then [数量] else 0 end) as '90'
    into #in
    from tab
    where [数量]>0
    group by [编号]select [编号], sum(case when datediff(dd,[日期],'2009-03-01')<30 then [数量] else 0 end) as '30',
    sum(case when datediff(dd,[日期],'2009-03-01') between 30 and 89 then [数量] else 0 end) as '3089',
    sum(case when datediff(dd,[日期],'2009-03-01')>=90 then [数量] else 0 end) as '90'
    into #out
    from tab
    where [数量]<0
    group by [编号]
    --select * from #in
    --select * from #outselect a.[编号], case when a.[3089]+a.[90]+b.[30]+b.[3089]+b.[90]>=0 then a.[30] else a.[30]+a.[3089]+a.[90]+b.[30]+b.[3089]+b.[90] end as '库龄小于30天',
    case when a.[90]+b.[30]+b.[3089]+b.[90]>=0 then a.[3089] else a.[3089]+a.[90]+b.[30]+b.[3089]+b.[90] end as '库龄30-89天',
    case when a.[90]+b.[30]+b.[3089]+b.[90]>0 then a.[90]+b.[30]+b.[3089]+b.[90] else 0 end as  '库龄90天以上'
    from #in a inner join #out b on a.[编号] = b.[编号]
      

  10.   


    /*---------------------------------------
    瘦狼阿亮 | 钱不是问题,问题是没钱!我乐于享受学习的过程
    ---------------------------------------*/--建立测试环境表
    declare @tmp table 
    (listID varchar(10),baseDate datetime,baseAmount smallint)/*表字段说明
    listID--编号
    baseDate--日期
    baseAmount--数量
    */--插入测试数据
    insert into @tmp 
    select '001','2009-01-01',30 union all
    select '001','2009-01-15',-2 union all
    select '001','2009-01-18',-5 union all
    select '001','2009-02-01',15 union all
    select '001','2009-02-02',-10 union all
    select '001','2009-02-15',-2 /*执行结果:
    (所影响的行数为 6 行)
    */--检查测试数据
    select * from @tmp/*执行结果:
    listID     baseDate                                               baseAmount 
    ---------- ------------------------------------------------------ ---------- 
    001        2009-01-01 00:00:00.000                                30
    001        2009-01-15 00:00:00.000                                -2
    001        2009-01-18 00:00:00.000                                -5
    001        2009-02-01 00:00:00.000                                15
    001        2009-02-02 00:00:00.000                                -10
    001        2009-02-15 00:00:00.000                                -2(所影响的行数为 6 行)
    */--查询结果与数据测试比对
    select basedate,adddate=datediff(day,basedate,'2009-03-01'),baseAmount from @tmp/*执行结果:
    basedate                                               adddate     baseAmount 
    ------------------------------------------------------ ----------- ---------- 
    2009-01-01 00:00:00.000                                59          30
    2009-01-15 00:00:00.000                                45          -2
    2009-01-18 00:00:00.000                                42          -5
    2009-02-01 00:00:00.000                                28          15
    2009-02-02 00:00:00.000                                27          -10
    2009-02-15 00:00:00.000                                14          -2(所影响的行数为 6 行)
    */--执行查询
    select 
    listID,
    smallin30_Amount=sum(case when datediff(dd,baseDate,'2009-03-01')<30 then baseAmount else 0 end),
    smallin89_Amount=sum(case when datediff(dd,baseDate,'2009-03-01') between 30 and 89 then baseAmount else 0 end),
    bigin90_Amount=sum(case when datediff(dd,baseDate,'2009-03-01')>=90 then baseAmount else 0 end) 
    from @tmp 
    group by listID/*执行结果:
    listID     smallin30_Amount smallin89_Amount bigin90_Amount 
    ---------- ---------------- ---------------- -------------- 
    001        3                23               0(所影响的行数为 1 行)
    */
      

  11.   

    从执行结果来看,语句应该是没有什么问题,但是发觉我所执行出来的结果和LZ给出的结果不太一致。
    想知道LZ的结果是如何得出的?如果我整错了,大家就一阵地拍砖吧……在执行查询以前,我做了一个数据比对查询:
    --查询结果与数据测试比对
    select basedate,adddate=datediff(day,basedate,'2009-03-01'),baseAmount from @tmp/*执行结果:
    basedate                                               adddate     baseAmount 
    ------------------------------------------------------ ----------- ---------- 
    2009-01-01 00:00:00.000                                59          30
    2009-01-15 00:00:00.000                                45          -2
    2009-01-18 00:00:00.000                                42          -5
    2009-02-01 00:00:00.000                                28          15
    2009-02-02 00:00:00.000                                27          -10
    2009-02-15 00:00:00.000                                14          -2(所影响的行数为 6 行)
    */这个查询就是为了验证自己的结果是否正确。1、从数据上看,以2009-03-01为截至日期,库龄小于30天的记录如下:
    basedate                                               adddate     baseAmount 
    ------------------------------------------------------ ----------- ---------- 
    2009-02-01 00:00:00.000                                28          15
    2009-02-02 00:00:00.000                                27          -10
    2009-02-15 00:00:00.000                                14          -2而库龄的合计为:15-10-2=32、而库龄大于或等于30天而小于89天的记录如下:
    basedate                                               adddate     baseAmount 
    ------------------------------------------------------ ----------- ---------- 
    2009-01-01 00:00:00.000                                59          30
    2009-01-15 00:00:00.000                                45          -2
    2009-01-18 00:00:00.000                                42          -5而库龄的合计为:30-2-5=233、最后一个大于或等于90天的记录在测试数据中没有,所以这个结果和LZ给出的结果一致。所以,想向楼主求证一下,到底楼主是不是要的这样的结果?
      

  12.   

     我不懂SQL,可以这样做吗?
    先按段搜出3个段的入库量:15,30,0
    再sum(所有出库)=19
    做先进先出减法:用sum减入库,从最早的开始,够减就清零,sum扣除。依次直到不够减:库存减去sum,sum=0,新库存表就是所得
      

  13.   

    SQL:
    select 
    case  
    --如果大于30天的库存+总消耗小于0,证明总消耗超过30天以后的库存,要使用30天内的库存来进行运算
        when (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where datediff(day,b,'2009-03-1') >=30 and C >0)<0
    then 
    (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where   c>0)
    else
    --'1'
    (select Isnull(sum(c),0) from liupengtttt where datediff(day,b,'2009-03-1') <30 and c>0)
    end as c1,
    case  
    --如果大于90天的库存+总消耗小于0,证明总消耗超过90天以后的库存,要使用30-89天的来进行运算
        when (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where datediff(day,b,'2009-03-1') >=90 and C >0)<0
    then 
    case 
    when (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where datediff(day,b,'2009-03-1') >=30 and C >0) >=0
    then (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where datediff(day,b,'2009-03-1') >=30 and C >0) 
    else
    '0'
    end
    else
    (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where datediff(day,b,'2009-03-1') >=30 and datediff(day,b,'2009-03-1')<90 and C >0 )
    end as c2,
    case  
    --如果大于90天的库存+总消耗大于等于0 证明 90天以后的库存超过总消耗,显示90天后库存与消耗的值,否则显示0
    when (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where datediff(day,b,'2009-03-1') >=90 and C >0)>=0 
    then (select Isnull(sum(c),0)+(select sum(c) from liupengtttt where c <0) from liupengtttt where datediff(day,b,'2009-03-1') >=90 and C >0)
    else 
    '0'
    end as c3引一朋友写的,已验证结果正确(加多种情况验证)