每年获取库存余额

时间:2016-11-11 07:05:11

标签: sql-server tsql pivot

我开始学习SQL Server,并希望就此问题提出想法。我有一个库存系统,其中包含以下表格:

  1. Delivery Table (Stock_ID, Stock_Name, Quantity, Delivery_Date)
  2. Disposal (Stock_ID, Stock_Name, Quantity, Disposal_Date)
  3. 示例Delivery表:

    Stock_ID    Stock_Name  Quantity    Delivery_Date
    0001        Plates      500         6/6/2015
    0002        Glasses     1000        6/7/2015
    0003        Plates      800         9/8/2016
    0004        Spoon       200         9/8/2016
    0005        Glasses     300         9/8/2016
    0006        Plates      1000        10/1/2017
    0007        Spoon       800         10/1/2017
    0008        Glasses     200         10/1/2017
    

    示例Disposal表:

    Stock_ID    Stock_Name  Quantity    Delivery_Date
    0001        Plates      20          9/6/2015
    0002        Glasses     100         10/7/2015
    0003        Plates      30          10/8/2016
    0004        Spoon       20          12/8/2016
    0005        Glasses     10          12/8/2016
    0006        Plates      100         12/1/2017
    0007        Spoon       20          12/1/2017
    0008        Glasses     20          12/1/2017
    

    基本上,我想获得每年的交割和处理摘要,以及所有股票的年终余额。

    结果表有望看起来像:

     Stock_Name: Plates
                                 2015           2016          2017
     1. Beginning Balance         0             480           1250
     2. Delivery                  500           800           1000
     3. Disposal                  20             30            100
     4. Balance                   480           1250          2150
    

    我正在尝试PIVOTUNPIVOT,但我似乎无法掌握如何使其发挥作用。请,任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:1)

棘手的一点是做平衡魔法。这仍然需要多年的硬编码,您可以使用动态SQL来构建查询,使其适用于任意日期。可能有一种更简单的方法可以做到这一点,但这有效:

create table Delivery (Stock_ID int, Stock_Name varchar(50), Quantity int, Delivery_Date date);
create table Disposal (Stock_ID int, Stock_Name varchar(50), Quantity int, Disposal_Date date);

insert into delivery values(0001, 'Plates' , 500  , '6/6/2015');
insert into delivery values(0002, 'Glasses', 1000 , '6/7/2015');
insert into delivery values(0003, 'Plates' , 800  , '9/8/2016');
insert into delivery values(0004, 'Spoon'  , 200  , '9/8/2016');
insert into delivery values(0005, 'Glasses', 300  , '9/8/2016');
insert into delivery values(0006, 'Plates' , 1000 , '10/1/2017');
insert into delivery values(0007, 'Spoon'  , 800  , '10/1/2017');
insert into delivery values(0008, 'Glasses', 200  , '10/1/2017');


insert into disposal values(0001, 'Plates' ,  20 , '9/6/2015');
insert into disposal values(0002, 'Glasses',  100, '10/7/2015');
insert into disposal values(0003, 'Plates' ,  30 , '10/8/2016');
insert into disposal values(0004, 'Spoon'  ,  20 , '12/8/2016');
insert into disposal values(0005, 'Glasses',  10 , '12/8/2016');
insert into disposal values(0006, 'Plates' ,  100, '12/1/2017');
insert into disposal values(0007, 'Spoon'  ,  20 , '12/1/2017');
insert into disposal values(0008, 'Glasses',  20 , '12/1/2017');

declare @stock varchar(50);
set @stock = 'Plates';

with transactions as
(
    select Quantity, 
        Delivery_Date as D 
    from Delivery 
    where Stock_Name = @stock
    union 
    select -Quantity, 
        Disposal_Date as D 
    from Disposal 
    where Stock_Name = @stock
),
ordered as 
(
    select *, ROW_NUMBER() over (order by D) rn
    from transactions
),
running as
(
    select *, sum(Quantity) over (order by rn rows unbounded preceding) running
    from ordered
),
ordered2 as
(
    select year(D) Y, 
        running as val, 
        row_number() over (partition by year(D) order by D) rnasc,
        row_number() over (partition by year(D) order by D desc) rndesc
    from running
),
data1 as 
(
    select 1 as ord, 'Beginning Balance' as row, o2.Y, isnull(b.val,0) as val
    from ordered2 o2
    outer apply (
        select val from ordered2 i2 where i2.Y = o2.Y - 1 and rndesc =1 
    ) b
    where rnasc = 1
),
data2 as
(
    select 2 as ord, 'Delivery' as row, year(Delivery_Date) as Y, sum(Quantity) as Quantity from Delivery where Stock_Name = @stock
    group by year(Delivery_Date)
),
data3 as 
(
    select 3 as ord, 'Disposal' as row, year(Disposal_Date) as Y, sum(Quantity) as Quantity from Disposal where Stock_Name = @stock
    group by year(Disposal_Date)
),
data4 as
(
    select 4 as ord, 'Balance' as row, o2.Y, val
    from ordered2 o2
    where rndesc = 1
),
data as 
(
    select * from data1
    union select * from data2
    union select * from data3
    union select * from data4
)
select row, [2015], [2016], [2017]
from 
(   
    select ord, row, y, val
    from data
) as s
pivot 
(
    sum(val)
    for y IN ([2015],[2016],[2017])
) as p
order by ord