2015-09-07 57 views
4

我有一个动态的PIVOT查询,其中的列是动态生成的。SQL Server中的PIVOT表中的动态列的总和

我的表:ATTENDANCE_MASTER 包含:ID,Stud_id,ATT_DATE,PRESENT

存储像数据:

ID Stud_id ATT_DATE PRESENT 
1  1  2015-08-1 1 
2  2  2015-08-1 0 
3  3  2015-08-1 1 
4  1  2015-08-2 0 
5  2  2015-08-2 1 
6  3  2015-08-2 1 

我创建PIVOT查询

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX); 

SET @columns = N''; 
SELECT @columns += N', p.' + QUOTENAME(ATT_DATE) 
    FROM (SELECT p.ATT_DATE FROM dbo.ATTENDANCE_MASTER AS p 
    GROUP BY p.ATT_DATE) AS x; 

SET @sql = N'SELECT Stud_id, ' + STUFF(@columns, 1, 2, '') + ' 
FROM 
(
    SELECT p.ATT_DATE, p.Stud_id, p.PRESENT FROM dbo.ATTENDANCE_MASTER AS p 
) AS j 
PIVOT 
(
    SUM(PRESENT) FOR ATT_DATE IN ('+ STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '') + ') 
) AS p;'; 
PRINT @sql; 
EXEC sp_executesql @sql; 

我需要的总和列如

Stud_ID 2015-08-01 2015-08-2 2015-08-3 Total 
1   1   0   1  2 
2   1   1   1  3 
3   1   1   0  2 
4   0   0   1  1 

请建议我解决方案。

在此先感谢。

+0

我知道如何使静态列的总和,但我不知道如何总结动态列 – QuaBizIT

+0

你现在有什么输出? –

+0

什么是动态的?日期列的数量? – 2015-09-07 12:30:52

回答

1

我最好先建议不要使用变量连接来创建你列的列表。 It's behaviour is undefined and can be unexpected。相反,使用SQL Server的XML扩展:

SET @Columns = (SELECT N', p.' + QUOTENAME(p.Att_Date) 
       FROM dbo.ATTENDANCE_MASTER AS p 
       GROUP BY p.ATT_DATE 
       ORDER BY p.ATT_DATE 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)'); 

然后,你可以简单地使用@Columns创造总的表达,所以使用:

', Total = ' + STUFF(REPLACE(@columns, ', p.[', ' + p.['), 1, 3, '') 

你喜欢的东西:

, Total = p.[2015-08-01] + p.[2015-08-02] 

你可以添加到你的动态SQL,所以一个完整的工作示例:

IF OBJECT_ID(N'tempdb..#T', 'U') IS NOT NULL DROP TABLE #T; 
CREATE TABLE #T ([ID] int, [Stud_id] int, [ATT_DATE] datetime, [PRESENT] int); 

INSERT INTO #T ([ID], [Stud_id], [ATT_DATE], [PRESENT]) 
VALUES 
    (1, 1, '2015-08-01 00:00:00', 1), 
    (2, 2, '2015-08-01 00:00:00', 0), 
    (3, 3, '2015-08-01 00:00:00', 1), 
    (4, 1, '2015-08-02 00:00:00', 0), 
    (5, 2, '2015-08-02 00:00:00', 1), 
    (6, 3, '2015-08-02 00:00:00', 1); 

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);    

SET @Columns = (SELECT N', p.' + QUOTENAME(REPLACE(CONVERT(VARCHAR(10), p.Att_Date, 111), '/', '-')) 
       FROM #T AS p 
       GROUP BY p.ATT_DATE 
       ORDER BY p.ATT_DATE 
       FOR XML PATH(''), TYPE 
       ).value('.', 'NVARCHAR(MAX)'); 

SET @sql = N'SELECT Stud_id, ' + STUFF(@columns, 1, 2, '') + ', Total = ' + STUFF(REPLACE(@columns, ', p.[', ' + p.['), 1, 3, '') + ' 
FROM 
(
    SELECT p.ATT_DATE, p.Stud_id, p.PRESENT FROM #T AS p 
) AS j 
PIVOT 
(
    SUM(PRESENT) FOR ATT_DATE IN ('+ STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '') + ') 
) AS p;'; 
PRINT @sql; 
EXEC sp_executesql @sql; 
+0

谢谢,它的工作.. – QuaBizIT

+0

我有一个更多的查询,我如何使用这两个聚合函数,如总和和计数。 – QuaBizIT

1

您可以添加GROUP BY WITH CUBE获得总在以下几点:

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX); 

SET @columns = N''; 
SELECT @columns += N', p.' + QUOTENAME(ATT_DATE) 
    FROM (SELECT p.ATT_DATE FROM dbo.ATTENDANCE_MASTER AS p 
    GROUP BY p.ATT_DATE) AS x; 

SET @sql = N'SELECT Stud_id, ' + STUFF(@columns, 1, 2, '') + ' 
FROM 
(
    SELECT p.ATT_DATE, p.Stud_id, p.PRESENT 
    FROM dbo.ATTENDANCE_MASTER AS p 
    GROUP BY p.ATT_DATE, p.Stud_id, p.PRESENT 
    WITH CUBE 
) AS j 
PIVOT 
(
    SUM(PRESENT) FOR ATT_DATE IN ('+ STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '') + ') 
) AS p;'; 
PRINT @sql; 
EXEC sp_executesql @sql;