Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 将项目相加,但分别计数,分组和子分组?_Sql_Sql Server_Accounting - Fatal编程技术网

Sql 将项目相加,但分别计数,分组和子分组?

Sql 将项目相加,但分别计数,分组和子分组?,sql,sql-server,accounting,Sql,Sql Server,Accounting,我希望每个月将top+base项目对的美元金额相加,同时仅将该项目对作为一个单位计算。看起来很容易吧 唯一重要的是,一个基数可以与多个TOP和多个零件号配对,这些收入需要根据这些不同的TOP零件号进行分组 1000吨底座可搭配tops 052和952。 9000T底座可搭配tops 087和787 销售订单表: order_num | part_num | month | quantity | revenue 01 052 January

我希望每个月将top+base项目对的美元金额相加,同时仅将该项目对作为一个单位计算。看起来很容易吧

唯一重要的是,一个基数可以与多个TOP和多个零件号配对,这些收入需要根据这些不同的TOP零件号进行分组

1000吨底座可搭配tops 052和952。 9000T底座可搭配tops 087和787

销售订单表:

order_num  |  part_num  |  month  |  quantity  |  revenue
01            052         January       1          4000
01            1000T       January       1          2000
02            052         January       1          4000
02            1000T       January       1          2000
03            087         January       1          5000
03            9000T       January       1          2500
04            087         January       1          5000
04            9000T       January       1          2500
05            787         February      1          5500
05            9000T       February      1          2500
06            952         January       1          3000
06            1000T       January       1          2000
我需要:

part_num  |  month  |  quantity  |  revenue
052         January       2          12000
952         January       1          5000
087         January       2          15000
787         January       0          0
787         February      1          8000
如果我按part_num分组,那么我的基础将从顶部分开。我不能在销售订单上求和,因为有些销售订单由不同的产品组成,尽管我的示例中没有。当销售订单号匹配时,我需要对每次出现的top+base组合求和,对吗?我可以在excel中做一些类似于SUMPRODUCT的操作,得到一个组合数组,然后对每个组合求和吗?感谢您的帮助。

示例数据

最后,我将月份改为整数,便于按时间顺序排序

declare @SalesOrder table
(
    num nvarchar(2),
    prt nvarchar(5),
    mth int,
    qty int,
    rev int
);

insert into @SalesOrder (num, prt, mth, qty, rev) values
('01', '052',   1, 1, 4000),
('01', '1000T', 1, 1, 2000),
('02', '052',   1, 1, 4000),
('02', '1000T', 1, 1, 2000),
('03', '087',   1, 1, 5000),
('03', '9000T', 1, 1, 2500),
('04', '087',   1, 1, 5000),
('04', '9000T', 1, 1, 2500),
('05', '787',   2, 1, 5500),
('05', '9000T', 2, 1, 2500),
('06', '952',   1, 1, 3000),
('06', '1000T', 1, 1, 2000);
解决方案

因为您还希望月份的销售额为零,所以顶部部分和月份分别从两个常用表表达式cte_topPrt和cte_mth中的数据中提取,并以交叉联接的方式组合以获得所有组合

with cte_topPrt as -- collect all top parts
(
    select distinct so.prt
    from @SalesOrder so
    where right(so.prt, 1) <> 'T'
),
cte_mth as -- collect all months (because you also want to see months with 0 sales)
(
    select distinct so.mth
    from @SalesOrder so
)
select  tp.prt as [part_num],
        m.mth as [month],
        coalesce(sum(case when so_tp.prt = so_c.prt then so_tp.qty else 0 end), 0) as [quantity],
        coalesce(sum(so_c.rev), 0) as [revenue]
from cte_topPrt tp
cross join cte_mth m
left join @SalesOrder so_tp -- sales order top part
    on  so_tp.prt = tp.prt
    and so_tp.mth = m.mth
left join @SalesOrder so_c -- sales order complete
    on so_c.num = so_tp.num
group by tp.prt, m.mth
order by m.mth, tp.prt;

这一个从匹配顶部和底部获得数量和收入。如果订单上还有其他内容,这一点很重要

;
with SalesOrder as (
    select order_num
        ,part_num
        ,[month]
        ,quantity
        ,revenue
    from (
        values ('01', '052',   'January',  1, 4000)
             , ('01', '1000T', 'January',  1, 2000)
             , ('01', '44',    'January',  1, 20000)
             , ('02', '052',   'January',  1, 4000)
             , ('02', '1000T', 'January',  1, 2000)
             , ('03', '087',   'January',  1, 5000)
             , ('03', '9000T', 'January',  1, 2500)
             , ('04', '087',   'January',  1, 5000)
             , ('04', '9000T', 'January',  1, 2500)
             , ('05', '787',   'February', 1, 5500)
             , ('05', '9000T', 'February', 1, 2500)
             , ('06', '952',   'January',  1, 3000)
             , ('06', '1000T', 'January',  1, 2000)
     ) as so(
        order_num,
        part_num,
        [month],
        quantity,
        revenue
    )
),
tops as (
    select part_num
    , base_part_num
    from (
        values ('052', '1000T')
             , ('952', '1000T')
             , ('087', '9000T')
             , ('787', '9000T')
    ) as t(
        part_num, 
        base_part_num
    )
),
months as (
    select 1 as MonthNumber
    , datename(month, '2000' + FORMAT(1,'00') + '01') as MonthName
    
    union all
    select m.MonthNumber + 1
    , datename(month, '2000' + FORMAT(m.MonthNumber + 1,'00') + '01')
    from months m
    where m.MonthNumber < 12
)


select x.part_num
, x.MonthName
, coalesce(o.quantity, 0) as quantity
, coalesce(o.revenue, 0) as revenue

from (
    select so.part_num
    , so.month
    , sum(so.quantity) as quantity
    , sum(so.revenue + baseorder.revenue) as revenue

    from SalesOrder so
      inner join tops t on t.part_num = so.part_num
      inner join SalesOrder baseorder on baseorder.part_num = t.base_part_num
                                     and baseorder.order_num = so.order_num

    group by so.part_num
    , so.month
) o
  full outer join (
    select m.MonthName
    , m.MonthNumber
    , t.part_num
    from months m
      , tops t
  ) x on x.part_num = o.part_num
     and x.MonthName = o.month

order by x.MonthNumber
, x.part_num

顶部和底部与您提供的数据有什么关系?零件号087、787、052和952是顶部。零件号1000T和2000T为基数。我想我还不清楚。这是两类成对的项。您的示例数据可能缺乏必要的复杂性。如果客户订购787顶部和1000吨底座怎么办。。。一次订购两件上衣和一个底座?这是不可能的,我们不允许客户订购没有底座的上衣。如果为顶部订购了替换底座,则会得到不同的名称1000T>1000T-P。
;
with SalesOrder as (
    select order_num
        ,part_num
        ,[month]
        ,quantity
        ,revenue
    from (
        values ('01', '052',   'January',  1, 4000)
             , ('01', '1000T', 'January',  1, 2000)
             , ('01', '44',    'January',  1, 20000)
             , ('02', '052',   'January',  1, 4000)
             , ('02', '1000T', 'January',  1, 2000)
             , ('03', '087',   'January',  1, 5000)
             , ('03', '9000T', 'January',  1, 2500)
             , ('04', '087',   'January',  1, 5000)
             , ('04', '9000T', 'January',  1, 2500)
             , ('05', '787',   'February', 1, 5500)
             , ('05', '9000T', 'February', 1, 2500)
             , ('06', '952',   'January',  1, 3000)
             , ('06', '1000T', 'January',  1, 2000)
     ) as so(
        order_num,
        part_num,
        [month],
        quantity,
        revenue
    )
),
tops as (
    select part_num
    , base_part_num
    from (
        values ('052', '1000T')
             , ('952', '1000T')
             , ('087', '9000T')
             , ('787', '9000T')
    ) as t(
        part_num, 
        base_part_num
    )
),
months as (
    select 1 as MonthNumber
    , datename(month, '2000' + FORMAT(1,'00') + '01') as MonthName
    
    union all
    select m.MonthNumber + 1
    , datename(month, '2000' + FORMAT(m.MonthNumber + 1,'00') + '01')
    from months m
    where m.MonthNumber < 12
)


select x.part_num
, x.MonthName
, coalesce(o.quantity, 0) as quantity
, coalesce(o.revenue, 0) as revenue

from (
    select so.part_num
    , so.month
    , sum(so.quantity) as quantity
    , sum(so.revenue + baseorder.revenue) as revenue

    from SalesOrder so
      inner join tops t on t.part_num = so.part_num
      inner join SalesOrder baseorder on baseorder.part_num = t.base_part_num
                                     and baseorder.order_num = so.order_num

    group by so.part_num
    , so.month
) o
  full outer join (
    select m.MonthName
    , m.MonthNumber
    , t.part_num
    from months m
      , tops t
  ) x on x.part_num = o.part_num
     and x.MonthName = o.month

order by x.MonthNumber
, x.part_num