使用分组SQL计算总计

时间:2018-02-17 13:31:47

标签: sql sql-server group-by aggregate-functions

我有一张桌子。 AVG_QTY_Total中的每个小计与每个MMODEL中使用的组件材料的数量相同。但是,对于Grand Total,我想计算3个模型的每个小计。因此,如果我手动总结,它应该是240 + 500 + 1200 = 1940.我怎么能得到它?

以下是我当前的查询,结果和期望结果。

当前查询:

  select YYYYMM,(case when GROUPING(MODEL) = 0 and
                  GROUPING(MODEL_DESC) = 1 and 
                  GROUPING(MATERIAL) = 1 
             then 'Total ' + MODEL
             when GROUPING(MODEL) = 1 and
                  GROUPING(MODEL_DESC) = 1 and
                  GROUPING(MATERIAL) = 1 then 'Grand Total'
             else MODEL
        end) as MMODEL,
       MODEL_DESC, MATERIAL,
       sum(AVG_QTY)/COUNT(MODEL) as AVG_QTY_Total,
       sum(PACK_QTY) as PACK_QTY_Total,
       sum(PACK_AMT) as PACK_AMT_Total 
From [SQLDB1].[dbo].[PACKING] 
group by grouping sets((YYYYMM,MODEL, MODEL_DESC ,MATERIAL),
                       (MODEL),
                       ()
                      );

当前结果:

YYYYMM  MMODEL  MODEL_DESC  MATERIAL    AVG_QTY_Total   PACK_QTY_Total  PACK_AMT_Total
201801  DE8     DE80001      A          240             20              3400
201801  DE8     DE80001      B          240             5               600
201801  DE8     DE80001      C          240             60              5000
NULL    Total DE8   NULL    NULL        240             85              9000
201801  DE8B    DE8B002      A          500             45              7600
201801  DE8B    DE8B002      B          500             10              1200
201801  DE8B    DE8B002      C          500             125             11000
NULL    Total DE8B  NULL    NULL        500             180             19800
201801  SF93    SF93005      A          1200            50              10200
201801  SF93    SF93005      B          1200            25              15000
201801  SF93    SF93005      C          1200            300             24000
NULL    Total SF93  NULL    NULL        1200            375             49200
NULL    Grand Total NULL    NULL        646             640             78000

期望结果:

YYYYMM  MMODEL  MODEL_DESC  MATERIAL    AVG_QTY_Total   PACK_QTY_Total  PACK_AMT_Total
201801  DE8     DE80001      A          240             20              3400
201801  DE8     DE80001      B          240             5               600
201801  DE8     DE80001      C          240             60              5000
NULL    Total DE8   NULL    NULL        240             85              9000
201801  DE8B    DE8B002      A          500             45              7600
201801  DE8B    DE8B002      B          500             10              1200
201801  DE8B    DE8B002      C          500             125             11000
NULL    Total DE8B  NULL    NULL        500             180             19800
201801  SF93    SF93005      A          1200            50              10200
201801  SF93    SF93005      B          1200            25              15000
201801  SF93    SF93005      C          1200            300             24000
NULL    Total SF93  NULL    NULL        1200            375             49200
NULL    Grand Total NULL    NULL        1940            640             78000

更新的解决方案1:

根据Gordon Linoff的回答,我设法将结果显示为期望答案。我也会尝试别人回答。

with t as (  select YYYYMM,(case when GROUPING(MODEL) = 0 and
                  GROUPING(MODEL_DESC) = 1 and 
                  GROUPING(MATERIAL) = 1 
             then MODEL
             when GROUPING(MODEL) = 1 and
                  GROUPING(MODEL_DESC) = 1 and
                  GROUPING(MATERIAL) = 1 then 'Grand Total'
             else MODEL
        end) as MMODEL,
       MODEL_DESC, MATERIAL,
       avg_qty as AVG_QTY_TT,
       sum(AVG_QTY)/COUNT(MODEL) as AVG_QTY_Total,
       sum(PACK_QTY) as PACK_QTY_Total,
       sum(PACK_AMT) as PACK_AMT_Total 
From [SQLDB1].[dbo].[PACKING] 
group by grouping sets((YYYYMM,MODEL, MODEL_DESC ,MATERIAL,avg_qty),
                       (MODEL),
                       ()
                      )),
     m as (
      select  Sum(  AVG_QTY_TT)/ COUNT(DISTINCT MODEL_DESC ) AS cnt
      from t

     )
select YYYYMM,MMODEL,MODEL_DESC,MATERIAL,
       (case when mmodel = 'Grand Total' then  (select cnt from m)
             else avg_qty_total
        end) as AVG_QTY_Total,
        PACK_QTY_Total,PACK_AMT_Total
from t;

3 个答案:

答案 0 :(得分:2)

您无法真正使用grouping sets。 。 。至少本身。

让我试着说服你想要1,940。这是三个不同组的平均值之和。在每组中,您正在计算平均值。那么为什么要在结合它们时总结它们呢?

可以尝试在事后调整值。基本上,运行您拥有的查询,并执行以下操作:

with t as (<your query here>),
     m as (
      select count(distinct model) cnt
      from t
      where yyyymm is null
     )
select . . .,
       (case when mmodel = 'Grand Total' then AVG_QTY_Total * (select cnt from m)
             else avg_qty_total
        end)
from t;

关于其他警告。由于整数的四舍五入问题,这将产生1938年。因此,您还需要修改算术以使用小数/浮点数而不是整数。

答案 1 :(得分:0)

你的桌子设计对我来说不是很清楚。我的理解是它看起来像这样:

YYYYMM  MMODEL  MODEL_DESC  MATERIAL    AVG_QTY_Total   PACK_QTY_Total  PACK_AMT_Total
201801  DE8     DE80001      A          240             20              3400
201801  DE8     DE80001      B          240             5               600
201801  DE8     DE80001      C          240             60              5000
201801  DE8B    DE8B002      A          500             45              7600
201801  DE8B    DE8B002      B          500             10              1200
201801  DE8B    DE8B002      C          500             125             11000
201801  SF93    SF93005      A          1200            50              10200
201801  SF93    SF93005      B          1200            25              15000
201801  SF93    SF93005      C          1200            300             24000

由于每个MMODEL的AVG_QTY_Total都相同,因此您可以通过以下方式识别主题:

SELECT DISTINCT MMODEL, AVG_QTY_Total
FROM [SQLDB1].[dbo].[PACKING]

如果您想在几天内完成此操作,也可以添加列YYYYMM

SELECT DISTINCT YYYYMM, MMODEL, AVG_QTY_Total
FROM [SQLDB1].[dbo].[PACKING]

然后,如果你想要总计,你可以简单地将上面的查询包装在另一个中,这样可以得到总和:

SELECT MMODEL, SUM(AVG_QTY_Total)
FROM (
    SELECT DISTINCT YYYYMM, MMODEL, AVG_QTY_Total
    FROM [SQLDB1].[dbo].[PACKING]
) TMP
GROUP BY MMODEL

它能回答你的问题吗?

答案 2 :(得分:0)

你可以做这样的事情

   WITH Group_Ttl AS 
(SELECT 
  YYYYMM, MMODEL,
MAX(AVG_QTY_Total) AS AVG_QTY_Total,
SUM(PACK_QTY_Total)  AS PACK_QTY_Total,
SUM(PACK_AMT_Total)  AS PACK_AMT_Total

FROM PACKING
GROUP BY YYYYMM, MMODEL
),Grandttl AS 
(
  SELECT
  SUM(AVG_QTY_Total)  AS AVG_QTY_Total,
    SUM(PACK_QTY_Total) AS PACK_QTY_Total,
    SUM(PACK_AMT_Total) AS PACK_AMT_Total

  FROM Group_Ttl
 )
 ,Rslt AS 
 (

    SELECT 
     YYYYMM,
     MMODEL,
     MODEL_DESC,
     MATERIAL,
     AVG_QTY_Total,
     PACK_QTY_Total,
     PACK_AMT_Total ,
     AVG_QTY_Total AS SortColumn
   FROM PACKING 

   UNION ALL

   SELECT 
     NULL,
    'Total ' + MMODEL,
     NULL,
     NULL,
     AVG_QTY_Total,
     PACK_QTY_Total,
     PACK_AMT_Total ,
    AVG_QTY_Total AS SortColumn
   FROM Group_Ttl

   UNION ALL

 SELECT 
     NULL,
     'Grand Total',
     NULL,
     NULL,
     AVG_QTY_Total,
     PACK_QTY_Total,
     PACK_AMT_Total,
     PACK_QTY_Total*PACK_AMT_Total AS SortColumn
   FROM Grandttl


  )

  SELECT 
     YYYYMM,
     MMODEL,
     MODEL_DESC,
     MATERIAL,
     AVG_QTY_Total,
     PACK_QTY_Total,
     PACK_AMT_Total  
 FROM Rslt
 ORDER  BY SortColumn,PACK_QTY_Total

sample link