如何使用动态 SQL 添加 2 列的值

How to use dynamic SQL to add value of 2 columns

我有一个小 table,其中包含学生的分数。 Table数据如下图所示。

在excel

中看起来像下面

我想使用动态 SQL 计算总数。我不想更新它。但是,我只想 select 使用动态 SQL.

计算总计的所有数据

请参考以下代码:

DECLARE @SQL NVARCHAR(MAX)=''
DECLARE @SNumberList NVARCHAR(MAX)=''
DECLARE @CalculatedLineNumbers NVARCHAR(MAX)=''

SELECT @CalculatedLineNumbers = @CalculatedLineNumbers+ ', '+ 
                CASE WHEN SNo = 7 THEN '[1] + [4]  [7]' 
                     WHEN SNo = 8 THEN '[2] + [5]  [8]'
                     WHEN SNo = 9 THEN '[3] + [6]  [7]'
                    ELSE QUOTENAME(SNo)  
                END
FROM Student

SELECT @SNumberList = @SNumberList+ ', '+QUOTENAME(SNo)  
FROM Student

SELECT @SNumberList=STUFF(@SNumberList, 1,1, ''), 
@CalculatedLineNumbers=STUFF(@CalculatedLineNumbers,1,1,'')

SET @SQL= '
        SELECT Year,'+@CalculatedLineNumbers+'
            FROM
            (
                SELECT   *

                from Student s) AS J
            PIVOT
            (
                MAX([Marks]) FOR Marks IN ('+@SNumberList+')
            ) AS P'

EXEC SP_EXECUTESQL @SQL

将 excel 屏幕截图作为预期输出,您只需指定感兴趣的 Year 即可完成此操作。

示例数据:

create table #sample_data
    (
        SNo int
        , [LineNo] int
        , ColumnNo int
        , LineName varchar(15)
        , ColumnName varchar(25)
        , Marks int
        , [Year] int
    )

insert into #sample_data
values (1, 1, 1, 'Math', 'Jay', 97, 2018)
    , (2, 1, 2, 'Math', 'Sam', 95, 2018)
    , (3, 1, 3, 'Math', 'Jack', 90, 2018)
    , (4, 2, 1, 'Science', 'Jay', 87, 2018)
    , (5, 2, 2, 'Science', 'Sam', 88, 2018)
    , (6, 2, 3, 'Science', 'Jack', 86, 2018)
    , (7, 3, 1, 'Total', 'Jay', null, 2018)
    , (8, 3, 2, 'Total', 'Sam', null, 2018)
    , (9, 3, 3, 'Total', 'Jack', null, 2018)

答案:

下面的脚本根据 Year 的设置确定相关的 ColumnName 值,并根据 ColumnNo 值强制列以预期顺序显示。旋转适当的记录后,查询使用 group by grouping sets 生成 Total 记录。

declare @ColumnNameList nvarchar(max)
    , @ColumnNameListSums nvarchar(max)
    , @DynamicQuery nvarchar(max)
    , @Year int = 2018 --set by OP in question

--get the full list of ColumnNames in a delimeter ("|") seperated string
set @ColumnNameList = 
    (
        select stuff((
            select '| ' + a.ColumnName
            from (
                select t.ColumnName
                , min(t.ColumnNo) as ColumnNo
                from #sample_data as t
                where t.[Year] = @Year
                group by t.ColumnName
                ) as a
            order by a.ColumnNo
            for xml path ('')
        ),1,1,'')
    );

--its possible to use the previous variable as well, but easier to create another one
set @ColumnNameListSums = 
    (
        select stuff((
            select ', sum(a.' + a.ColumnName + ') as ' + a.ColumnName
            from (
                select t.ColumnName
                , min(t.ColumnNo) as ColumnNo
                from #sample_data as t
                where t.[Year] = @Year
                group by t.ColumnName
                ) as a
            order by a.ColumnNo
            for xml path ('')
        ),1,1,'')
    );

set @DynamicQuery = 
    '
        select isnull(b.LineName, ''Total'') as LineName
        , b.' + ltrim(replace(@ColumnNameList, '| ', ', b.')) + '
        from (
            select a.LineName
            , ' + @ColumnNameListSums + '
            from (
                select t.LineName
                , t.ColumnName
                , t.Marks
                , t.[Year]
                from #sample_data as t
                where t.LineName <> (''Total'') --don''t need it, will generate totals later
                and t.[Year] = ' + cast(@Year as char(4)) + '
                ) as a
            pivot (max(a.Marks) for a.ColumnName in ([' + ltrim(replace(@ColumnNameList, '| ', '], [')) + '])) as a
            group by grouping sets
                (
                    (
                        a.LineName
                    )
                    ,
                    (
                        --purposefully left empty
                    )
                )
            ) as b  
    '

print @DynamicQuery --in order to see query being executed
exec(@DynamicQuery);

输出:

给定示例数据,生成以下输出。

+----------+-----+-----+------+
| LineName | Jay | Sam | Jack |
+----------+-----+-----+------+
| Math     |  97 |  95 |   90 |
| Science  |  87 |  88 |   86 |
| Total    | 184 | 183 |  176 |
+----------+-----+-----+------+

SQL 服务器不执行 "double headers",因此您无法在查询输出中获取 2018。您可以在 excel.

的第 1 行中手动添加“2018”的顶部 header