Параметры из базы данных Cognos Audit - PullRequest
0 голосов
/ 06 февраля 2019

Использование:IBM Cognos Analytics 11.0.7Microsoft SQL Server 2016

Начну с признания, что мои знания по синтаксическому анализу XML слабые.

Я пытаюсь использовать базу данных Cognos Audit для получения полезной информации о параметрах отчета, которые пользователи выбрали при запускеотчеты.(В частности, я подозреваю, что некоторые пользователи загружают всю витрину данных.) Я настроил ведение журнала параметров.Когда я запускаю запрос для получения информации о параметре, я вижу его в столбце с именем COGIPF_PARAMETER_VALUE_BLOB, который представляет собой ntext, содержащий XML.У меня возникают проблемы при использовании этого 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

, который возвращает эту строку:

+---------------+------+---------+---------+------+
| ValueMultiple | true | Canada  | Canada  | NULL |
+---------------+------+---------+---------+------+

..., но не возвращает строку для Китая или Дании,Я также хочу видеть ...

+---------------+------+---------+---------+------+
| ValueMultiple | true | China   | China   | NULL |
+---------------+------+---------+---------+------+
| ValueMultiple | true | Denmark | Denmark | NULL |
+---------------+------+---------+---------+------+

Кроме того, вы можете видеть, что возвращаемый столбец ParamType содержит все NULL.Я попытался SOAP-ENC:arrayType, но SQL-сервер сказал мне XQuery [value ()]: имя «SOAP-ENC» не обозначает пространство имен. Это кажется мне странным (опять же, ограниченное знание XML), потому чтоЯ вижу xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" в первой строке XML.Я могу справиться с этим, включив в свой запрос что-то вроде REPLACE(xml, 'SOAP-ENC:', '').

Любая помощь приветствуется, но два моих главных вопроса на данный момент:

Как сделать так, чтобы запрос выводил эти данные в пригодную для использования таблицу (включая отсутствующие строки)?Требуется ли для этого процесс ETL, который я мог бы встроить в SSIS, или есть хороший способ выполнить это в запросе SQL?

Как проверить значение атрибута SOAP-ENC:arrayType, чтобы определить, сколько элементовв значении?Должен ли я просто использовать предложенный код REPLACE, или есть лучший способ?

1 Ответ

0 голосов
/ 21 марта 2019

Я наконец-то решил это.Запрос ниже даст результаты, которые мне нужны.Если вывод велик, это действительно медленно.Я могу использовать эту же технологию, чтобы ежедневно записывать хранимую процедуру для ETL-данных в таблицу.Мое тестирование показывает, что это сократит время выполнения запроса примерно на 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'
...