来自 Cognos Audit 数据库的参数
Parameters from Cognos Audit Database
使用:
IBM Cognos 分析 11.0.7
微软 SQL 服务器 2016
首先我要承认我的 XML 解析知识薄弱。
我正在尝试使用 Cognos Audit 数据库获取有关用户在 运行ning 报告时选择的报告参数的有用信息。 (具体来说,我怀疑某些用户正在下载整个数据集市。)我已经设置了参数记录。当我 运行 查询获取参数信息时,我在名为 COGIPF_PARAMETER_VALUE_BLOB
的列中看到它,它是包含 XML 的 ntext。我在将此 XML 与审计数据库中的其他数据一起使用时遇到问题,因此我想编写一个查询脚本,将其呈现为视图。
我根据样本数据创建了一个简单的报告,并包含了几个提示。当我 运行 报告、回答提示并单击完成时,我在审计数据库中看到结果参数:
<parameterValues xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:bus="http://developer.cognos.com/schemas/bibus/3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parameterValue[5]">
<item xsi:type="parameterValue">
<name xsi:type="xs:string">Date</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 7, 2019</display>
<use xsi:type="xs:string">2019-02-07T00:00:00.000</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">ValueSingle</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Austria</display>
<use xsi:type="xs:string">Austria</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">Text</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">asdf</display>
<use xsi:type="xs:string">asdf</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">DateRange</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="boundRangeParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<end xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 14, 2019</display>
<use xsi:type="xs:string">2019-02-14T23:59:59.999</use>
</end>
<start xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 6, 2019</display>
<use xsi:type="xs:string">2019-02-06T00:00:00.000</use>
</start>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">ValueMultiple</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[3]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Canada</display>
<use xsi:type="xs:string">Canada</use>
</item>
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">China</display>
<use xsi:type="xs:string">China</use>
</item>
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Denmark</display>
<use xsi:type="xs:string">Denmark</use>
</item>
</value>
</item>
</parameterValues>
请注意,在名为 ValueMultiple 的参数中,我选择了三个值:加拿大、中国、丹麦。
我创建了这个查询:
select b.value('(text())[1]', 'varchar(128)') as 'ParamName'
, b.value('(../value/@arrayType)[1]', 'varchar(128)') as 'ParamType'
, b.value('(../value/item/inclusive)[1]', 'varchar(128)') as 'Inclusive'
, b.value('(../value/item/display)[1]', 'varchar(128)') as 'Display'
, b.value('(../value/item/use)[1]', 'varchar(128)') as 'Use'
--, b.value('(../value/item/start/inclusive)[1]', 'varchar(128)') as 'RangeStartInclusive'
--, b.value('(../value/item/start/display)[1]', 'varchar(128)') as 'RangeStartDisplay'
--, b.value('(../value/item/start/use)[1]', 'varchar(128)') as 'RangeStartUse'
--, b.value('(../value/item/end/inclusive)[1]', 'varchar(128)') as 'RangeEndInclusive'
--, b.value('(../value/item/end/display)[1]', 'varchar(128)') as 'RangeEndDisplay'
--, b.value('(../value/item/end/use)[1]', 'varchar(128)') as 'RangeEndUse'
from @x.nodes('/parameterValues/item/name') a(b)
order by 1
第 return 这一行:
+---------------+------+---------+---------+------+
| ValueMultiple | true | Canada | Canada | NULL |
+---------------+------+---------+---------+------+
...但不 return 中国或丹麦的行。我也想看...
+---------------+------+---------+---------+------+
| ValueMultiple | true | China | China | NULL |
+---------------+------+---------+---------+------+
| ValueMultiple | true | Denmark | Denmark | NULL |
+---------------+------+---------+---------+------+
此外,您可以看到 ParamType returned 列包含所有 NULL。我尝试了 SOAP-ENC:arrayType
,但 SQL 服务器告诉我 XQuery [value()]:名称 "SOAP-ENC" 不表示名称空间。 这看起来很奇怪对我来说(同样,XML 知识有限)因为我在 XML 的第一行看到 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
。我可以通过在查询中包含类似 REPLACE(xml, 'SOAP-ENC:', '')
的内容来处理此问题。
感谢您的帮助,但此时我的两个主要问题是:
如何使查询将此数据输出到可用的 table(包括缺失的行)?这是否需要我可以在 SSIS 中构建的 ETL 过程,或者是否有在 SQL 查询中执行此过程的好方法?
如何检查 SOAP-ENC:arrayType
属性的值以确定值中有多少个元素?我应该只使用我建议的 REPLACE
代码,还是有更好的方法?
我终于解决了这个问题。下面的查询将产生我需要的结果。如果输出很大,这真的很慢。我可以使用相同的技术编写一个存储过程,每天将数据 ETL 到 table 中。我的测试表明,这会将查询 运行 次减少大约 99%。
declare @start datetime
declare @end datetime
set @start = {ts '2019-02-06 08:00:00.000'}
set @end = {ts '2019-02-06 14:30:00.000'}
select u.COGIPF_USERNAME
, p.COGIPF_LOCALTIMESTAMP
, r.COGIPF_REPORTNAME
, p.name
, p.inclusive
, p.type
, p.display
, p.[use]
, p.RangeStartInclusive
, p.RangeStartDisplay
, p.RangeStartUse
, p.RangeEndInclusive
, p.RangeEndDisplay
, p.RangeEndUse
from (
-- SQL to see user-selected parameters for report runs
-- this uses the "parameterValues" parameter type
-- join to COGIPF_RUNREPORT on COGIPF_REQUESTID and COGIPF_LOCALTIMESTAMP
select q2.COGIPF_LOCALTIMESTAMP
, q2.COGIPF_REQUESTID
, q2.name
--, item.val.query('.') as 'val'
, item.val.value('inclusive[1]', 'varchar(5)') as 'inclusive'
, item.val.value('(@type)[1]', 'varchar(128)') as 'type'
, case
when item.val.value('(@type)[1]', 'varchar(128)') = 'simpleParmValueItem' then item.val.value('display[1]', 'varchar(128)')
end as 'display'
, case
when item.val.value('(@type)[1]', 'varchar(128)') = 'simpleParmValueItem' then item.val.value('use[1]', 'varchar(128)')
end as 'use'
, item.val.value('(start/inclusive)[1]', 'varchar(128)') as RangeStartInclusive
, item.val.value('(start/display)[1]', 'varchar(128)') as RangeStartDisplay
, item.val.value('(start/use)[1]', 'varchar(128)') as RangeStartUse
, item.val.value('(end/inclusive)[1]', 'varchar(128)') as RangeEndInclusive
, item.val.value('(end/display)[1]', 'varchar(128)') as RangeEndDisplay
, item.val.value('(end/use)[1]', 'varchar(128)') as RangeEndUse
from (
select q.COGIPF_LOCALTIMESTAMP
, q.COGIPF_REQUESTID
, param.item.value('name[1]', 'varchar(128)') as 'name'
--, opt.item.value('value[1]', 'varchar(128)') as 'value'
, param.item.query('.') as 'item'
, cast(replace(replace(param.item.value('(value/@arrayType)[1]', 'varchar(128)'), 'parmValueItem[', ''), ']', '') as int) as 'arrayLen'
from (
select p.COGIPF_LOCALTIMESTAMP
, p.COGIPF_REQUESTID
, cast(replace(replace(replace(replace(cast(p.COGIPF_PARAMETER_VALUE_BLOB as varchar(max)), 'xs:', ''), 'xsi:', ''), 'bus:', ''), 'SOAP-ENC:', '') as xml) as 'params'
from COGIPF_PARAMETER p
where p.COGIPF_PARAMETER_NAME = 'parameterValues'
and p.COGIPF_LOCALTIMESTAMP between @start and @end
--and p.COGIPF_LOCALTIMESTAMP > cast(getdate() as date)
) q
cross apply q.params.nodes('/parameterValues/item') as param(item)
) q2
cross apply q2.item.nodes('/item/value/item') as item(val)
where q2.arrayLen <> 0
) p
inner join COGIPF_RUNREPORT r on r.COGIPF_REQUESTID = p.COGIPF_REQUESTID
and r.COGIPF_LOCALTIMESTAMP = p.COGIPF_LOCALTIMESTAMP
inner join COGIPF_USERLOGON u on u.COGIPF_SESSIONID = r.COGIPF_SESSIONID
where u.COGIPF_LOGON_OPERATION = 'logon'
and u.COGIPF_USERNAME = 'lastname, firstname'
使用:
IBM Cognos 分析 11.0.7
微软 SQL 服务器 2016
首先我要承认我的 XML 解析知识薄弱。
我正在尝试使用 Cognos Audit 数据库获取有关用户在 运行ning 报告时选择的报告参数的有用信息。 (具体来说,我怀疑某些用户正在下载整个数据集市。)我已经设置了参数记录。当我 运行 查询获取参数信息时,我在名为 COGIPF_PARAMETER_VALUE_BLOB
的列中看到它,它是包含 XML 的 ntext。我在将此 XML 与审计数据库中的其他数据一起使用时遇到问题,因此我想编写一个查询脚本,将其呈现为视图。
我根据样本数据创建了一个简单的报告,并包含了几个提示。当我 运行 报告、回答提示并单击完成时,我在审计数据库中看到结果参数:
<parameterValues xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:bus="http://developer.cognos.com/schemas/bibus/3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parameterValue[5]">
<item xsi:type="parameterValue">
<name xsi:type="xs:string">Date</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 7, 2019</display>
<use xsi:type="xs:string">2019-02-07T00:00:00.000</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">ValueSingle</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Austria</display>
<use xsi:type="xs:string">Austria</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">Text</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">asdf</display>
<use xsi:type="xs:string">asdf</use>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">DateRange</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[1]">
<item xsi:type="boundRangeParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<end xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 14, 2019</display>
<use xsi:type="xs:string">2019-02-14T23:59:59.999</use>
</end>
<start xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Feb 6, 2019</display>
<use xsi:type="xs:string">2019-02-06T00:00:00.000</use>
</start>
</item>
</value>
</item>
<item xsi:type="parameterValue">
<name xsi:type="xs:string">ValueMultiple</name>
<value xsi:type="SOAP-ENC:Array" SOAP-ENC:arrayType="parmValueItem[3]">
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Canada</display>
<use xsi:type="xs:string">Canada</use>
</item>
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">China</display>
<use xsi:type="xs:string">China</use>
</item>
<item xsi:type="simpleParmValueItem">
<inclusive xsi:type="xs:boolean">true</inclusive>
<display xsi:type="xs:string">Denmark</display>
<use xsi:type="xs:string">Denmark</use>
</item>
</value>
</item>
</parameterValues>
请注意,在名为 ValueMultiple 的参数中,我选择了三个值:加拿大、中国、丹麦。
我创建了这个查询:
select b.value('(text())[1]', 'varchar(128)') as 'ParamName'
, b.value('(../value/@arrayType)[1]', 'varchar(128)') as 'ParamType'
, b.value('(../value/item/inclusive)[1]', 'varchar(128)') as 'Inclusive'
, b.value('(../value/item/display)[1]', 'varchar(128)') as 'Display'
, b.value('(../value/item/use)[1]', 'varchar(128)') as 'Use'
--, b.value('(../value/item/start/inclusive)[1]', 'varchar(128)') as 'RangeStartInclusive'
--, b.value('(../value/item/start/display)[1]', 'varchar(128)') as 'RangeStartDisplay'
--, b.value('(../value/item/start/use)[1]', 'varchar(128)') as 'RangeStartUse'
--, b.value('(../value/item/end/inclusive)[1]', 'varchar(128)') as 'RangeEndInclusive'
--, b.value('(../value/item/end/display)[1]', 'varchar(128)') as 'RangeEndDisplay'
--, b.value('(../value/item/end/use)[1]', 'varchar(128)') as 'RangeEndUse'
from @x.nodes('/parameterValues/item/name') a(b)
order by 1
第 return 这一行:
+---------------+------+---------+---------+------+
| ValueMultiple | true | Canada | Canada | NULL |
+---------------+------+---------+---------+------+
...但不 return 中国或丹麦的行。我也想看...
+---------------+------+---------+---------+------+
| ValueMultiple | true | China | China | NULL |
+---------------+------+---------+---------+------+
| ValueMultiple | true | Denmark | Denmark | NULL |
+---------------+------+---------+---------+------+
此外,您可以看到 ParamType returned 列包含所有 NULL。我尝试了 SOAP-ENC:arrayType
,但 SQL 服务器告诉我 XQuery [value()]:名称 "SOAP-ENC" 不表示名称空间。 这看起来很奇怪对我来说(同样,XML 知识有限)因为我在 XML 的第一行看到 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
。我可以通过在查询中包含类似 REPLACE(xml, 'SOAP-ENC:', '')
的内容来处理此问题。
感谢您的帮助,但此时我的两个主要问题是:
如何使查询将此数据输出到可用的 table(包括缺失的行)?这是否需要我可以在 SSIS 中构建的 ETL 过程,或者是否有在 SQL 查询中执行此过程的好方法?
如何检查 SOAP-ENC:arrayType
属性的值以确定值中有多少个元素?我应该只使用我建议的 REPLACE
代码,还是有更好的方法?
我终于解决了这个问题。下面的查询将产生我需要的结果。如果输出很大,这真的很慢。我可以使用相同的技术编写一个存储过程,每天将数据 ETL 到 table 中。我的测试表明,这会将查询 运行 次减少大约 99%。
declare @start datetime
declare @end datetime
set @start = {ts '2019-02-06 08:00:00.000'}
set @end = {ts '2019-02-06 14:30:00.000'}
select u.COGIPF_USERNAME
, p.COGIPF_LOCALTIMESTAMP
, r.COGIPF_REPORTNAME
, p.name
, p.inclusive
, p.type
, p.display
, p.[use]
, p.RangeStartInclusive
, p.RangeStartDisplay
, p.RangeStartUse
, p.RangeEndInclusive
, p.RangeEndDisplay
, p.RangeEndUse
from (
-- SQL to see user-selected parameters for report runs
-- this uses the "parameterValues" parameter type
-- join to COGIPF_RUNREPORT on COGIPF_REQUESTID and COGIPF_LOCALTIMESTAMP
select q2.COGIPF_LOCALTIMESTAMP
, q2.COGIPF_REQUESTID
, q2.name
--, item.val.query('.') as 'val'
, item.val.value('inclusive[1]', 'varchar(5)') as 'inclusive'
, item.val.value('(@type)[1]', 'varchar(128)') as 'type'
, case
when item.val.value('(@type)[1]', 'varchar(128)') = 'simpleParmValueItem' then item.val.value('display[1]', 'varchar(128)')
end as 'display'
, case
when item.val.value('(@type)[1]', 'varchar(128)') = 'simpleParmValueItem' then item.val.value('use[1]', 'varchar(128)')
end as 'use'
, item.val.value('(start/inclusive)[1]', 'varchar(128)') as RangeStartInclusive
, item.val.value('(start/display)[1]', 'varchar(128)') as RangeStartDisplay
, item.val.value('(start/use)[1]', 'varchar(128)') as RangeStartUse
, item.val.value('(end/inclusive)[1]', 'varchar(128)') as RangeEndInclusive
, item.val.value('(end/display)[1]', 'varchar(128)') as RangeEndDisplay
, item.val.value('(end/use)[1]', 'varchar(128)') as RangeEndUse
from (
select q.COGIPF_LOCALTIMESTAMP
, q.COGIPF_REQUESTID
, param.item.value('name[1]', 'varchar(128)') as 'name'
--, opt.item.value('value[1]', 'varchar(128)') as 'value'
, param.item.query('.') as 'item'
, cast(replace(replace(param.item.value('(value/@arrayType)[1]', 'varchar(128)'), 'parmValueItem[', ''), ']', '') as int) as 'arrayLen'
from (
select p.COGIPF_LOCALTIMESTAMP
, p.COGIPF_REQUESTID
, cast(replace(replace(replace(replace(cast(p.COGIPF_PARAMETER_VALUE_BLOB as varchar(max)), 'xs:', ''), 'xsi:', ''), 'bus:', ''), 'SOAP-ENC:', '') as xml) as 'params'
from COGIPF_PARAMETER p
where p.COGIPF_PARAMETER_NAME = 'parameterValues'
and p.COGIPF_LOCALTIMESTAMP between @start and @end
--and p.COGIPF_LOCALTIMESTAMP > cast(getdate() as date)
) q
cross apply q.params.nodes('/parameterValues/item') as param(item)
) q2
cross apply q2.item.nodes('/item/value/item') as item(val)
where q2.arrayLen <> 0
) p
inner join COGIPF_RUNREPORT r on r.COGIPF_REQUESTID = p.COGIPF_REQUESTID
and r.COGIPF_LOCALTIMESTAMP = p.COGIPF_LOCALTIMESTAMP
inner join COGIPF_USERLOGON u on u.COGIPF_SESSIONID = r.COGIPF_SESSIONID
where u.COGIPF_LOGON_OPERATION = 'logon'
and u.COGIPF_USERNAME = 'lastname, firstname'