0

上下文: 我在 SQL Server 中有一个视图,可以在用户运行 SSRS 报告 (ReportServer.dbo.ExecutionLog) 时跟踪用户输入的参数。大约 50 个报告参数以字符串形式保存在具有 ntext 数据类型的单列中。我想为每个参数将这一列分成多列。

详细信息: 我这样查询报表参数:

SELECT ReportID, [Parameters]
FROM ReportServer.dbo.ExecutionLog
WHERE ReportID in (N'redacted')
and [Status] in (N'rsSuccess')
ORDER BY TimeEnd DESC

以下是结果的一小部分:

alpha=123&bravo=9%2C33%2C76%2C23&charlie=91&delta=29&echo=11%2F2%2F2018%2012%3A00%3A00%20AM&foxtrot=11%2F1%2F2030%2012%3A00%3A00%20AM

问题:

我怎样才能让结果看起来像这样:

在此处输入图像描述

SQL Server 2017 对 Python 友好。在这种情况下,Python 是否是一种更好的语言,仅用于解析目的?

我在这里这里这里看到过类似的主题。这些参数是动态的,因此不适用通过涉及计数字符的 SQL 字符串函数进行解析。这个问题不仅仅与我有关,因为有大量的人使用 SSRS。以更易于理解的方式跟踪和格式化参数对 SSRS 的所有用户都很有价值。

4

3 回答 3

0

在 & 字符上拆分字符串。

在等号字符上进一步将每一行分成两列。

在第二列中,替换%2C为逗号字符和%2F正斜杠字符,依此类推,根据需要使用任何其他替换。

使用动态枢轴以您想要的格式查询上述内容。

于 2019-01-21T18:46:32.413 回答
0

这是一种使用内置STRING_SPLIT. 我只是不确定日期之后的东西的逻辑是什么,所以我会丢弃它,但我把它留给你决定。

演示

declare @table table (ReportID int identity(1,1),  [Parameters] varchar(8000))
insert into @table
values
('alpha=123&bravo=9%2C33%2C76%2C23&charlie=91&delta=29&echo=11%2F2%2F2018%2012%3A00%3A00%20AM&foxtrot=11%2F1%2F2030%2012%3A00%3A00%20AM')
,('alpha=457893&bravo=9%2C33%2C76%2C23&charlie=91&delta=29&echo=11%2F2%2F2018%2012%3A00%3A00%20AM&foxtrot=11%2F1%2F2030%2012%3A00%3A00%20AM')

select 
    ReportID
    ,[Parameters]
    ,alpha = max(iif(value like 'alpha%',substring(value,charindex('=',value) + 1,99),null))
    ,bravo = max(iif(value like 'bravo%',substring(value,charindex('=',value) + 1,99),null))
    ,charlie = max(iif(value like 'charlie%',substring(value,charindex('=',value) + 1,99),null))
    ,delta = max(iif(value like 'delta%',substring(value,charindex('=',value) + 1,99),null))
    ,echo = max(iif(value like 'echo%',substring(value,charindex('=',value) + 1,99),null))
    ,foxtrot = max(iif(value like 'foxtrot%',substring(value,charindex('=',value) + 1,99),null))
from @table
cross apply string_split(replace(replace([Parameters],'%2C',','),'%2F','/'),'&')
group by ReportID, [Parameters]

或者,如果它们不是静态的,您可以使用动态枢轴。需要一些按摩才能使您的列按正确的顺序排列。

演示

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(substring([value],0,charindex('=',[value]))) 
                from myTable
                cross apply string_split(replace(replace([Parameters],'%2C',','),'%2F','/'),'&')
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


select @cols

set @query = 'SELECT ReportID, ' + @cols + ' from 
            (
                select ReportID
                    , ColName = substring([value],0,charindex(''='',[value]))
                    , ColVal = substring([value],charindex(''='',[value]) + 1,99)
                from myTable
                cross apply string_split(replace(replace([Parameters],''%2C'','',''),''%2F'',''/''),''&'')
           ) x
            pivot 
            (
                 max(ColVal)
                for ColName in (' + @cols + ')
            ) p '

execute(@query)
于 2019-01-21T19:31:34.650 回答
0

这是一种以大量替换开始的方法。
对字符串进行 url 解码并将其转换为 XML 类型。

然后它使用 XML 函数来获取列的值。

示例片段:

declare @Table table ([Parameters] varchar(200));

insert into @Table ([Parameters]) values
('alpha=123&bravo=9%2C33%2C76%2C23&charlie=91&delta=29&echo=11%2F2%2F2018%2012%3A00%3A00%20AM&foxtrot=11%2F1%2F2030%2012%3A00%3A00%20AM');

select 
x.query('/x[key="alpha"]/val').value('.', 'int') as alpha,
x.query('/x[key="bravo"]/val').value('.', 'varchar(30)') as bravo,
x.query('/x[key="charlie"]/val').value('.', 'varchar(30)') as charlie,
x.query('/x[key="delta"]/val').value('.', 'varchar(30)') as delta,
convert(date, x.query('/x[key="echo"]/val').value('.', 'varchar(30)'), 103)as echo,
convert(date, x.query('/x[key="foxtrot"]/val').value('.', 'varchar(30)'), 103) as foxtrot
from @Table
cross apply (select cast('<x><key>'+ 
  replace(replace(replace(replace(replace(
    replace([Parameters], 
       '%2C',','), 
       '%2F','/'), 
       '%20',' '), 
       '%3A',':'),
       '=','</key><val>'), 
       '&','</val></x><x><key>') 
     +'</val></x>' as XML) as x) ca

在这里测试db<>fiddle

于 2019-01-21T21:33:23.303 回答