【问题标题】:How to use dynamic SQL to add value of 2 columns如何使用动态 SQL 添加 2 列的值
【发布时间】:2018-07-14 19:46:48
【问题描述】:

我有一个包含学生分数的小桌子。表格数据如下图所示。

在excel中如下所示

我想使用动态 SQL 计算总数。我不想更新它。但是,我只想使用动态 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

【问题讨论】:

    标签: sql-server tsql pivot dynamic-sql unpivot


    【解决方案1】:

    将 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 Server 不执行“双标头”,因此您无法在查询的输出中获得 2018。您可以在excel的第1行手动添加“2018”的顶部标题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-03
      • 1970-01-01
      • 2017-03-21
      • 1970-01-01
      • 2018-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多