动态数据库按案例分组(Unpivot)

时间:2015-09-10 21:10:13

标签: sql sql-server tsql

好的我有一个情况:我创建了一个表并插入了一些值:

CREATE TABLE temp1
(
ProcessName varchar(50),
ProcessNo  varchar(50),
ProcessPages varchar(50),
ProcessClass varchar (50)
)

INSERT INTO temp1 VALUES ('PRO1','PR012','5','O');
INSERT INTO temp1 VALUES ('PRO1','PR012','4','Y');
INSERT INTO temp1 VALUES ('PRO1','PR012','10','Y');
INSERT INTO temp1 VALUES ('PRO1','PR012','7','Y');
INSERT INTO temp1 VALUES ('PRO1','PR012','6','Y');
INSERT INTO temp1 VALUES ('PRO1','PR012','14','K');
INSERT INTO temp1 VALUES ('PRO1','PR012','23','Y');
INSERT INTO temp1 VALUES ('PRO1','PR012','45','L');
INSERT INTO temp1 VALUES ('PRO1','PR012','52','Y');
INSERT INTO temp1 VALUES ('PRO2','PR022','3','K');
INSERT INTO temp1 VALUES ('PRO2','PR022','5','T');
INSERT INTO temp1 VALUES ('PRO2','PR022','6','Y');
INSERT INTO temp1 VALUES ('PRO2','PR022','5','Y');
INSERT INTO temp1 VALUES ('PRO2','PR022','5','H');
INSERT INTO temp1 VALUES ('PRO2','PR022','8','Y');
INSERT INTO temp1 VALUES ('PRO2','PR022','5','T');
INSERT INTO temp1 VALUES ('PRO2','PR022','2','Y');
INSERT INTO temp1 VALUES ('PRO2','PR022','3','T');
INSERT INTO temp1 VALUES ('PRO2','PR022','3','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','5','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','10','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','15','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','25','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','35','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','45','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','55','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','25','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','25','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','20','Y');
INSERT INTO temp1 VALUES ('PRO3','PR032','3','O');
INSERT INTO temp1 VALUES ('PRO3','PR032','3','K');

我正试图推出这个理想的结果。

|       | With Y        | Without Y
|1p     | 5             | 8        
|2p     | 6             | 0
|3p     | 1             | 1
|4p     | 7             | 1
|5p     | 2             | 0  
|Total  | 21            | 10 

With_y是WHERE [ProcessClass] =' Y'而且Without_Y是WHERE [ProcessClass]<>' Y'

我的代码如下:

DECLARE  @ColumnNames1 NVARCHAR(MAX)
DECLARE  @SQL1 NVARCHAR(MAX)

SELECT @ColumnNames1=Stuff((SELECT DISTINCT ',' + Quotename([ProcessName])
                   FROM temp1
                   FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET @SQL1= '
SELECT * FROM (
    SELECT [ProcessName], 
        COUNT(CASE WHEN [ProcessPages] >=  1 and [ProcessPages] <=  5 THEN ''1p'' END) AS [1p],
        COUNT(CASE WHEN [ProcessPages] >=  6 and [ProcessPages] <= 10 THEN ''2p'' END) AS [2p],
        COUNT(CASE WHEN [ProcessPages] >= 11 and [ProcessPages] <= 16 THEN ''3p'' END) AS [3p],
        COUNT(CASE WHEN [ProcessPages] >= 17 and [ProcessPages] <= 50 THEN ''4p'' END) AS [4p],
        COUNT(CASE WHEN [ProcessPages] >  50 THEN ''5p'' END) AS [5p],
        COUNT([ProcessName]) AS Total
    FROM temp1
    WHERE [ProcessClass]=''Y'' 
    GROUP BY [ProcessName]) AS SOURCE
    UNPIVOT ( val FOR [''] IN ([1p],[2p],[3p],[4p],[5p],[Total]) ) U
    PIVOT ( MAX(val) FOR [ProcessName] IN('+@ColumnNames1 +') ) As PivotTable'

    --print @sql
EXECUTE sp_executesql @SQL1

返回:

如何使其达到上述所需报告

2 个答案:

答案 0 :(得分:1)

要获得您想要的结果,您根本不需要使用动态SQL,而是可以使用简单的group bygrouping sets

WITH t AS (
    SELECT 
       [ProcessName] =    
       CASE 
          WHEN ProcessPages >=  1 AND ProcessPages <=  5 THEN '1p' 
          WHEN ProcessPages >=  6 AND ProcessPages <= 10 THEN '2p'
          WHEN ProcessPages >= 11 AND ProcessPages <= 16 THEN '3p'
          WHEN ProcessPages >= 17 AND ProcessPages <= 50 THEN '4p'
          WHEN ProcessPages >  50                        THEN '5p' 
       END
       , ProcessClass    
    FROM temp1
)
SELECT
    ProcessName = CASE WHEN GROUPING(ProcessName) = 0 THEN ProcessName ELSE 'Total' END 
    , With_y     = COUNT(CASE WHEN [ProcessClass] =  'Y' THEN ProcessClass END)
    , Without_Y  = COUNT(CASE WHEN [ProcessClass] <> 'Y' THEN ProcessClass END)
FROM t
GROUP BY GROUPING SETS (ProcessName, ());

-- use the next line for versions <2008:
-- GROUP BY ProcessName WITH ROLLUP;

为了避免重复case表达式,我使用了一个公用表表达式。

Sample SQL Fiddle

答案 1 :(得分:0)

看起来您的类别列表是动态的,因此没有理由使用动态sql或所有那些枢轴/非透视。

SELECT
        '1p ' + cast(sum(y1p) as varchar(8)) + ' ' + cast(sum(n1p) as varchar(8)) +
       ' 2p ' + cast(sum(y2p) as varchar(8)) + ' ' + cast(sum(n2p) as varchar(8)) +
       ' 3p ' + cast(sum(y3p) as varchar(8)) + ' ' + cast(sum(n3p) as varchar(8)) +
       ' 4p ' + cast(sum(y4p) as varchar(8)) + ' ' + cast(sum(n4p) as varchar(8)) +
       ' 5p ' + cast(sum(y5p) as varchar(8)) + ' ' + cast(sum(n5p) as varchar(8)) +
    ' Total ' + cast(sum(ty)  as varchar(8)) + ' ' + cast(sum(tn)  as varchar(8)) 
FROM (
    SELECT ProcessName, 
        COUNT(CASE WHEN ProcessClass  = 'Y' and ProcessPages between  1 and  5 THEN 1 END) AS y1p,
        COUNT(CASE WHEN ProcessClass  = 'Y' and ProcessPages between  6 and 10 THEN 1 END) AS y2p,
        COUNT(CASE WHEN ProcessClass  = 'Y' and ProcessPages between 11 and 16 THEN 1 END) AS y3p,
        COUNT(CASE WHEN ProcessClass  = 'Y' and ProcessPages between 17 and 50 THEN 1 END) AS y4p,
        COUNT(CASE WHEN ProcessClass  = 'Y' and ProcessPages > 50 THEN 1 END) AS y5p,
        COUNT(CASE WHEN ProcessClass <> 'Y' and ProcessPages between  1 and  5 THEN 1 END) AS n1p,
        COUNT(CASE WHEN ProcessClass <> 'Y' and ProcessPages between  6 and 10 THEN 1 END) AS n2p,
        COUNT(CASE WHEN ProcessClass <> 'Y' and ProcessPages between 11 and 16 THEN 1 END) AS n3p,
        COUNT(CASE WHEN ProcessClass <> 'Y' and ProcessPages between 17 and 50 THEN 1 END) AS n4p,
        COUNT(CASE WHEN ProcessClass <> 'Y' and ProcessPages > 50 THEN 1 END) AS n5p,
        COUNT(CASE WHEN ProcessClass  = 'Y' THEN 1 END) AS ty,
        COUNT(CASE WHEN ProcessClass <> 'Y' THEN 1 END) AS tn
    FROM temp1
    GROUP BY ProcessName
) AS SOURCE

请注意,自我发布以来,您已编辑了所需的输出格式。