如何将SQL查询结果列名称作为第一行

时间:2017-03-23 16:24:21

标签: sql sql-server sql-server-2012 dynamicquery

我有一个动态SQL查询,可以在执行后获取结果集。但是,我从SQL服务器引擎返回结果的UI模型并没有提供渲染查询列名的方法。

由于查询的动态特性,我无法在设计时对列名进行硬编码。所以我的问题是如何获取列名以及查询返回的数据集?

此查询:

DECLARE @SQLSTATMENT nvarchar(1000) 
SELECT @SQLSTATEMENT = ' 
                            SELECT 
                                convert(date, DATEADDED) DATEADDED
                                ,COUNT(1) as NUMBEROFRECORDS
                            FROM 
                                dbo.CONSTITUENT 
                            GROUP BY 
                                convert(date, DATEADDED)
                            ORDER BY 
                                convert(date, DATEADDED) DESC
                                '
            Exec (@SQLSTATEMENT);

给我这张桌子(Original Image):

+ ---------- + --------------- +
| DATEADDED  | NUMBEROFRECORDS |
+ ---------- + --------------- +
| 2017-03-14 | 1               |
| 2017-03-10 | 1               |
| 2016-07-07 | 5               |
| 2016-06-29 | 3               |
| 2016-06-15 | 1               |
| 2014-11-11 | 465             |
| 2005-06-09 | 11              |
| 2005-04-13 | 1               |
| 2005-02-28 | 2               |
+ ---------- + --------------- +

但我想要这个(Original Image):

+ ---------- + --------------- +
| DATEADDED  | NUMBEROFRECORDS |
+ ---------- + --------------- +
| DATEADDED  | NUMBEROFRECORDS |
| 2017-03-14 | 1               |
| 2017-03-10 | 1               |
| 2016-07-07 | 5               |
| 2016-06-29 | 3               |
| 2016-06-15 | 1               |
| 2014-11-11 | 465             |
| 2005-06-09 | 11              |
| 2005-04-13 | 1               |
| 2005-02-28 | 2               |
+ ---------- + --------------- +

由于

2 个答案:

答案 0 :(得分:1)

这是可行的,但不是很漂亮。传递动态SQL的存储过程将更加清晰

我们实际上是在动态SQL中执行动态SQL

一个警告:我保留了RN

字段

示例(使用我的FRED系列数据)

-- This is Your Base/Initial Query, or the only portion you need to supply
Declare @SQL varchar(max) = 'Select Updated  as Updated,Count(*) as NumberOfRecords From [dbo].[FRED-Series] Group By Updated'

Select @SQL = '
;with cte0 as ('+@SQL+')
    , cte1 as (Select *,RN = Row_Number() over (Order By (Select null)) From cte0 ) 
    , cte2 as (
        Select A.RN,C.*
         From  cte1 A
         Cross Apply (Select XMLData=cast((Select A.* for XML Raw) as xml)) B
         Cross Apply (
                        Select Item   = attr.value(''local-name(.)'',''varchar(100)'')
                              ,Value  = attr.value(''.'',''varchar(max)'') 
                              ,ColNr  = Row_Number() over (Order By (Select Null))
                         From  B.XMLData.nodes(''/row'') as A(r)
                         Cross Apply A.r.nodes(''./@*'') AS B(attr)
                         Where attr.value(''local-name(.)'',''varchar(100)'') not in (''RN'')
                     ) C
      )
Select Distinct RN=0,Item,Value=Item,ColNr Into #Temp From cte2 Union All Select * from cte2

Declare @SQL varchar(max) = Stuff((Select '','' + QuoteName(Item) From #Temp Where RN=0 Order by ColNr For XML Path('''')),1,1,'''') 
Select  @SQL = ''Select '' + @SQL + '' From (Select RN,Item,Value From #Temp ) A Pivot (max(Value) For [Item] in ('' + @SQL + '') ) p''
Exec(@SQL);
'
Exec(@SQL)

<强>返回

Updated     NumberOfRecords
Updated     NumberOfRecords
2017-03-22  597
2017-03-23  40
2017-03-20  228
2017-03-21  1404

只是一些评论

cte0是您的主要查询

cte1将获取初始查询的结果并添加行号

cte2将动态取消您的数据

为方便起见,将cte2的结果放入#temp表中(假设允许这样做)

然后我们执行动态数据透视

答案 1 :(得分:0)

使用列名联合静态查询。您必须将第二个查询的结果转换为varchar或nvarchar,因此它们与列名称的数据类型相同。

DECLARE @SQLSTATMENT nvarchar(1000) 
SELECT @SQLSTATEMENT = ' 
    SELECT
        ''DATEADDED'' AS [DATEADDED]
        ,''NUMBEROFRECORDS'' AS [NUMBEROFRECORDS]

    SELECT 
        CAST(convert(date, DATEADDED) AS NVARCHAR(MAX)
        ,CAST(COUNT(1) AS NVARCHAR(MAX))
    FROM 
        dbo.CONSTITUENT 
    GROUP BY 
        convert(date, DATEADDED)
    ORDER BY 
        convert(date, DATEADDED) DESC
'
Exec (@SQLSTATEMENT);

说到这一点,您应该能够通过代码引用列名,而不必将它们添加到查询中。这样就可以保留结果集的数据类型。