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

时间:2016-02-17 01:43:44

标签: sql-server tsql

我有一个场景。我有一个函数,可以正确计算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)

任何意见都将受到赞赏。

2 个答案:

答案 0 :(得分:0)

你可以试试这个: -

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, ())

答案 1 :(得分:0)

所以我理解的是你想要将代码的两个部分组合成一个函数。如果下面提到的功能适合您,请告诉我。您可以根据需要在下面的功能中进行调整:

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')