带有区分大小写列名的T-SQL Dynamic Pivot

时间:2014-04-14 20:13:22

标签: sql sql-server reporting-services pivot case-sensitive

我正在处理SQL Server的查询(目前是2008 R2) - 我的目标是生成一个结果集,列出特定路径下SSRS中定义的每个报告以及一个包含列的网格对于服务器上每个唯一命名的报告参数,网格的内容为"选中标记" (例如,非空值)每个报告+参数组合,其对应的报告具有带有相应名称的参数。查询需要对报表参数名称区分大小写 - 查询的一个目的是识别具有拼写不一致的参数的报表。

我能够使用多种技术编写该查询(有些人可能称之为丑陋的黑客):

use ReportServer
go

declare @path nvarchar(255);
set @path = N'SSRS Path To Folder'

-- return a table with two columns: ReportName, ParameterName with one row for each
-- distinct ReportName + ParameterName combination
select
  t.Name as ReportName,
  pn.value collate Latin1_General_CS_AI as ParameterName
into
  #rp
from
  (
    -- return a table with two columns: ReportName and ParameterNames (comma-separated list of
    -- parameters in declaration order)
    select
      [Name],
      (select STUFF((select ', ' + p.n.value('.', 'varchar(255)') 
        from ParameterXml.nodes('/Parameters/Parameter/Name') p(n) 
        for xml path('')), 1, 2, '')
      ) as ParameterNames
    from
    (
      select
        *,
        CAST(Parameter as xml) as ParameterXml
      from
        [Catalog] 
    ) c
    where
      [Path] like '/' + @path + '/%'
      and [Type] = 2
  ) t
  cross apply dbo.SplitString(t.ParameterNames) pn

-- Pivot the above result into a table with one row per report and one column for each
-- distinct report parameter name.  Parameter-named columns contain a flag - 1 or null - 
-- that indicates whether the report corresponding to that row defines the parameter 
-- corresponding to that column.
create database CS_Temp collate Latin1_General_CS_AI;
go

use CS_Temp
go

declare @cols nvarchar(MAX), @query nvarchar(MAX);
set @cols = STUFF(
            (
              select 
                distinct ','+QUOTENAME(rp.ParameterName) 
              from 
                #rp rp
              for xml path(''), type).value('.', 'nvarchar(max)'
            ),1,1,''
          );

set @query = 'SELECT ReportName, ' + @cols + ' from 
  (
      select ReportName, 1 as Used, ParameterName from #rp
  ) x
  pivot 
  (
      max(Used) for ParameterName in (' + @cols + ')
  ) p
';

execute(@query)
go

drop table #rp

use ReportServer;
go

drop database CS_Temp;
go

(来自Erland Sommarskog / Itzik Ben-Gan的SplitString函数,来自Aaron Bertrand的动态枢轴技术)。这个查询确实有效,但它很慢而且很难看 - 这对我的用例来说实际上是可以的。我想知道的是,是否有更好的方法可以使用与区分大小写的列名称相比,我可以使用区分大小写的方法创建数据库。 ,切换到该上下文并执行数据透视查询。除了为数据库元数据提供排序规则(即数据透视查询结果中的列名)之外,数据库没有任何用途。

1 个答案:

答案 0 :(得分:1)

要使用PIVOT命令,您需要具有区分大小写的排序规则,以便区分大小写列,如您所见。我喜欢新的临时CS数据库的狡猾但是我能想到的其他几种方法并不需要它:

  • 在报告中完成所有这些!不是在SQL中。更轻松!但并没有真正回答这个问题
  • 而不是使用PIVOT,在每个参数的查询中使用单独的列进行旧式操作,例如https://stackoverflow.com/a/5799709/8479。您可以自己生成动态SQL,因此它不是那么乏味。关于这一点的好处是它只有CASE语句比较需要区分大小写,这是数据,因此使用表(或子查询)的排序规则。在输出数据之后,你永远不会引用列名,它们只是列别名,所以如果有几个相同(根据db排序),它就没问题了。
  • 而不是仅使用参数名称作为列名,包括一些参数编号前缀或后缀,如01_myParam,02_MyParam,03_yourparam。您将在子查询中计算前缀,并再次进行数据比较,因此不需要区分大小写的列。当在PIVOT语句中使用列时,数字前缀/后缀表示不需要区分大小写。显然,缺点是你当然在列名中有一个烦人的数字:)如果你真的关心你可以在列名中使用不可见的字符来区分多个相同的列名,例如: “myParam”,“MyParam”,“myparam”,仅后缀具有重复名称的内容,并使用STUFF添加多个字符或具有子索引,其中包含您索引的非打印字符表。
相关问题