T-SQL Dynamic Pivot с именами столбцов с учетом регистра

Я работаю над запросом 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

(функция SplitString от Erland Sommarskog/Itzik Ben-Gan, динамическая сводная техника от Aaron Bertrand). Этот запрос действительно работает, но он медленный и уродливый - на самом деле это нормально для моего варианта использования. Однако мне интересно, есть ли лучший способ заставить стержень работать с именами столбцов, чувствительными к регистру, чем то, что я здесь сделал: на самом деле создавая базу данных с сортировкой по регистру, переключаясь на этот контекст и выполняя сводный запрос. База данных не имеет никакой цели, кроме предоставления сопоставления метаданных базы данных - то есть имен столбцов в результате сводного запроса.

Ответ 1

Чтобы использовать команду PIVOT, вам нужно иметь сортировку с учетом регистра, чтобы иметь столбцы, чувствительные к регистру, как вы уже нашли. Мне нравится хитрость нового временного CS db, но есть несколько других подходов, о которых я могу думать, которые не требуют этого:

  • сделайте все это в отчете! не в SQL. Полегче! Но на самом деле не отвечающий на вопрос
  • вместо использования PIVOT сделайте это в старом стиле с отдельным столбцом в вашем запросе на параметр, например fooobar.com/info/336332/.... Вы можете генерировать динамический SQL самостоятельно, так что это не так утомительно. Самое замечательное в этом - это только сравнения операторов CASE, которые должны быть чувствительны к регистру, которые являются данными, и поэтому использует сортировку таблицы (или подзапроса). Вы никогда не ссылаетесь на имена столбцов после вывода данных, это просто псевдонимы столбцов, поэтому это хорошо, если их несколько (в соответствии с сортировкой db).
  • вместо использования имен параметров в качестве имен столбцов, включите префикс или суффикс числа параметров, например 01_myParam, 02_MyParam, 03_yourparam. Вы будете вычислять префикс в подзапросе, и, опять же, для сравнения данных не нужны столбцы, чувствительные к регистру. Когда столбцы используются в инструкции PIVOT, числовой префикс/суффикс означает, что чувствительность к регистру не требуется. Ясно, что недостаток - у вас есть раздражающее число в названии столбца, конечно:) Если вы действительно волновались, вы могли бы использовать невидимый символ в именах столбцов, чтобы различать несколько одинаковых одинаковых имен столбцов, например. "myParam", "MyParam", "myparam", только суффикс, которые имеют дублирующее имя и используют STUFF для добавления нескольких символов или имеют подзапрос с таблицей непечатаемых символов, в которую вы индексируете.