根据不同的条件对两个不同的列进行分组和求和

Posted

技术标签:

【中文标题】根据不同的条件对两个不同的列进行分组和求和【英文标题】:Grouping and Summing two different columns based on different conditions 【发布时间】:2016-02-17 01:43:43 【问题描述】:

我在这里有一个场景。我有一个函数可以正确计算 Non_CombinedSet 列的值。此 Non_CombinedSet 使用 case 语句根据特定条件进行分组和计数的条件。 (请看下面的代码:

   --Table creation
CREATE TABLE [dbo].[testrun](
    [ProcessName] [varchar](50) NULL,
    [ProcessMEMid] [varchar](50) NULL,
    [ProcessID] [varchar](50) NULL,
    [ProcessSequence] [varchar](50) NULL,
    [ProcessSheets] [varchar](50) NULL,
    [ProcessMABSW] [varchar](50) NULL
) ON [PRIMARY

--insert statement
INSERT INTO [dbo].[testrun]
           ([ProcessName]
           ,[ProcessMEMid]
           ,[ProcessID]
           ,[ProcessSequence]
           ,[ProcessSheets]
           ,[ProcessMABSW])

            VALUES 
                   ('A1','01-01','X1','1','3','M'),
                   ('B2','01-01','X1','5','2','M'),
                   ('C3','01-02','X1','6','4','M'),
                   ('D4','01-02','X1','10','8','M'),
                   ('E5','01-03','X1','30','18','M'),
                   ('F6','01-03','X1','25','25','M'),
                   ('G7','01-03','X1','50','30','M'),
                   ('H8','01-03','X1','25','15','M'),
                    ('I9','01-04','X1','15','10','M'),
                    ('J10','01-04','X1','15','3','M'),

                   ('K11','01-05','X1','10','2','M'),

                   ('L12','01-05','X1','05','15','M'),

                   ('M13','01-06','X1','05','11','M'),

                   ('N14','01-06','X1','05','13','M'),

                   ('O15','01-01','X1','05','50','M'),
                    ('P16','01-07','X1','05','7','M'),
                     ('Q17','01-07','X1','05','2','S'),
                      ('R18','01-07','X1','05','1','S'),
                       ('S16','01-08','X1','05','7','S'),
                        ('T16','01-08','X1','05','7','S')



--Function Creation
Create FUNCTION [dbo].[fn_HIC_6] 
(   
@ProcessID VARCHAR(50)
)
RETURNS TABLE 
AS
RETURN 
(
    -- Add the SELECT statement with parameter references here
    WITH CTE_Temp AS (
    SELECT 
       ProcessName =    
       CASE 
          WHEN ProcessSheets >=  1 AND ProcessSheets <=  5 THEN '1of'
          WHEN ProcessSheets >=  6 AND ProcessSheets <= 10 THEN '2of'
          WHEN ProcessSheets >= 11 AND ProcessSheets <= 16 THEN '3of'
          WHEN ProcessSheets >= 17 AND ProcessSheets <= 50 THEN '4of'
          WHEN ProcessSheets >  50   THEN '5of'
       END
       , ProcessMABSW
       ,ProcessID
       ,[ProcessMEMid]    
    FROM [dbo].[testrun]
)
SELECT  ProcessName = CASE WHEN GROUPING(ProcessName) = 0 THEN ProcessName ELSE 'Total' END 
       --,Combined_Set  = COUNT(DISTINCT(CASE WHEN ProcessMABSW = 'M' THEN [ProcessMEMid]  END))
     ,Combined_Set     = COUNT(CASE WHEN ProcessMABSW = 'M' THEN ProcessMABSW   END)
    , Non_CombinedSet = COUNT(CASE WHEN ProcessMABSW  <> 'M' THEN ProcessMABSW  END)
FROM CTE_Temp
WHERE ProcessID=@ProcessID
GROUP BY GROUPING SETS (ProcessName, ())


)

但是,对于 Combined_Set 列,我无法正确计算我要查找的内容。孤立地,我可以很容易地得到正确的结果。请看下面的代码:

--Combined_Set 
WITH CTE_TEMP
AS
(

SELECT 
     [ProcessMEMid],Sum(isNULL(Cast([ProcessSheets] as int),0))  Combined
      ,COUNT([ProcessMEMid]) AS 'Total'
     FROM [dbo].[testrun]
     WHERE [ProcessID]='X1'
     AND [ProcessMABSW]='M'
     GROUP BY
        [ProcessMEMid]


)SELECT    
       CASE 
          WHEN Combined >=  1 AND Combined <=  5 THEN '1of'
          WHEN Combined >=  6 AND Combined <= 10 THEN '2of'
          WHEN Combined >= 11 AND Combined <= 16 THEN '3of'
          WHEN Combined >= 17 AND Combined <= 49 THEN '4of'
          WHEN Combined >  49   THEN '5of'
          --WHEN Combined >=1 AND Combined > 49 THEN CAST([Total] as varchar(10))
          ELSE CAST([Total] as varchar(10))
       END
       ,
       COUNT([ProcessMEMid]) AS 'Combined'
FROM  CTE_TEMP
GROUP BY 
CASE 
          WHEN Combined >=  1 AND Combined <=  5 THEN '1of'
          WHEN Combined >=  6 AND Combined <= 10 THEN '2of'
          WHEN CombIned >= 11 AND Combined <= 16 THEN '3of' 
          WHEN Combined >= 17 AND Combined <= 49 THEN '4of'
          WHEN Combined >  49   THEN '5of'
          --WHEN Combined >=1 AND Combined > 49 THEN CAST([Total] as varchar(10))
          ELSE CAST([Total] as varchar(10))
          END 

UNION 


    SELECT 
      CASE 
          WHEN 1=1 THEN 'Total'
          WHEN 2=2 THEN 'Total'
          WHEN 3=3 THEN 'Tota'
          WHEN 4=4 THEN 'Total'
          WHEN 5=5 THEN 'Total'
          END 
      ,COUNT(distinct [ProcessMEMid]) AS 'Total'
     FROM [dbo].[testrun]
     WHERE ProcessID='X1'
     AND ProcessMABSW='M'

以上返回正确的值。我现在的问题是如何将 Combined_Set 查询合并到我的函数中(这部分代码Combined_Set = COUNT(CASE WHEN ProcessMABSW = 'M' THEN ProcessMABSW END)

我们将不胜感激。

【问题讨论】:

【参考方案1】:

所以我的理解是您希望将代码的两个部分组合成一个函数。让我知道下面提到的功能是否适合您。您可以根据需要在下面的功能中进行调整:

alter function testfn(@processid as varchar(100))
returns table
as
return
(
with cte1 as
(
select isnull(cast(case   
            when ProcessSheets between 1 and 5 then '1of'
            when ProcessSheets between 6 and 10 then '2of'
            when ProcessSheets between 11 and 16 then '3of'
            when ProcessSheets between 17 and 50 then '4of'
            when ProcessSheets > 50 then '5of' 
       end as varchar(100)),'Total') as processname,
       count(case when processmabsw = 'M' then 1 end) as combined_set,
       count(case when processmabsw <> 'M' then 1 end) as noncombined_set,
       processid
from testrun
group by 
        grouping sets(case   
            when ProcessSheets between 1 and 5 then '1of'
            when ProcessSheets between 6 and 10 then '2of'
            when ProcessSheets between 11 and 16 then '3of'
            when ProcessSheets between 17 and 50 then '4of'
            when ProcessSheets > 50 then '5of' 
       end,()),processid
),cte2 as 
(
select processmemid,sum(cast(processsheets as int)) as combined,count(processmemid) as total,processid
from testrun
where processmabsw = 'm'
group by processmemid,processid
),cte3 as
(
select isnull(cast(case
            when combined between 1 and 5 then '1of'
            when combined between 6 and 10 then '2of'
            when combined between 11 and 16 then '3of'
            when combined between 17 and 49 then '4of'
            when combined > 49 then '5of'
       end as varchar(10)),'Total') as processname,count(ProcessMEMid) as combined,processid
from cte2      
group by 
        grouping sets(case
            when combined between 1 and 5 then '1of'
            when combined between 6 and 10 then '2of'
            when combined between 11 and 16 then '3of'
            when combined between 17 and 49 then '4of'
            when combined > 49 then '5of'
        end,()),processid
)
select a.processname,a.combined_set,a.noncombined_set,b.combined from cte1 as a
left join cte3 as b
on a.processname = b.processname
where a.processid = @processid

)
go

select * from testfn('x1')

【讨论】:

【参考方案2】:

你能试试这个吗:-

SELECT  ProcessName = CASE WHEN GROUPING(ProcessName) = 0 THEN ProcessName ELSE 'Total' END 
        ,Combined_Set     = CASE WHEN ProcessMABSW = 'M' THEN COUNT(ProcessMABSW) ELSE 0   END
        , Non_CombinedSet = CASE WHEN ProcessMABSW  <> 'M' THEN COUNT(ProcessMABSW) ELSE 0  END
FROM CTE_Temp
WHERE ProcessID=@ProcessID
GROUP BY GROUPING SETS (ProcessName, ())

【讨论】:

汉克斯,但它没有用。请记住,Combined_Set 和 Non_CombinedSet 的逻辑是完全不同的。前一组,然后根据条件计算总和(请参阅上面解释它的代码),而后一组并根据特定条件计算。 —— 任何人的想法?

以上是关于根据不同的条件对两个不同的列进行分组和求和的主要内容,如果未能解决你的问题,请参考以下文章

Mongodb对来自聚合方面的两个相似数据数组进行分组和求和

如何使用熊猫对与给定条件匹配的列中的值求和?

如何对视图中的列进行求和/分组/排序

试图找到一种方法来根据在 excel 中不同表中查找的条件对字段求和

如何根据不同df中提供的索引值对数据框中的特定列进行求和。返回总和和布尔 T/F

根据重叠时段对数据进行分组或求和