Вопрос XML-запроса

8

Я пытаюсь сгенерировать запрос SQL, чтобы получить значения «DATE» из следующего SQL XML:

Скриншот

Я пробовал что-то подобное, но я не думаю, что понимаю концепции.

select 
   xConfig.value('(/SearchjobConfig/QueryString/SearchCriteria/ExpressionSet/SimpleAttributeExpression) [1]','nvarchar(max)') 
from 
    Job 

Вот XML в виде текста:

<SearchJobConfig>
  <QueryID>1072</QueryID>
  <QueryString>
    <SearchCriteria name="Search query" >
      <ExpressionSet logicalOperator="AND">
        <SimpleAttributeExpression displayName="Date" npmPropertyId="4" searchOperation="GREATER_EQUAL" dataType="string" caseSensitive="false">2019-06-01T04:00:00</SimpleAttributeExpression>
        <SimpleAttributeExpression displayName="Date" npmPropertyId="4" searchOperation="LESS_EQUAL" dataType="string" caseSensitive="false">2019-06-13T03:59:59</SimpleAttributeExpression>
        <SimpleAttributeExpression displayName="Class" npmPropertyId="1056" searchOperation="EQUALS" dataType="int32" caseSensitive="false">65</SimpleAttributeExpression>
      </ExpressionSet>
    </SearchCriteria>
  </QueryString>
</SearchJobConfig>

Ожидаемый результат будет Даты:

2019-06-01T04:00:00
2019-06-13T03:59:59

и что потребуется, чтобы получить результаты в той же строке .. пример:

date_val_start date_val_end 2019-06-01T04:00:00 2019-06-13T03:59:59

Я использую SQL Server 2012 Enterprise Edition.

Джон
источник

Ответы:

8

Это дает вам то, что вы хотите?

DECLARE @x XML = '
<SearchJobConfig>
  <QueryID>1072</QueryID>
  <QueryString>
    <SearchCriteria name="Search query" >
      <ExpressionSet logicalOperator="AND">
        <SimpleAttributeExpression displayName="Date" npmPropertyId="4" searchOperation="GREATER_EQUAL" dataType="string" caseSensitive="false">2019-06-01T04:00:00</SimpleAttributeExpression>
        <SimpleAttributeExpression displayName="Date" npmPropertyId="4" searchOperation="LESS_EQUAL" dataType="string" caseSensitive="false">2019-06-13T03:59:59</SimpleAttributeExpression>
        <SimpleAttributeExpression displayName="Class" npmPropertyId="1056" searchOperation="EQUALS" dataType="int32" caseSensitive="false">65</SimpleAttributeExpression>
      </ExpressionSet>
    </SearchCriteria>
  </QueryString>
</SearchJobConfig>
'

DECLARE @Job TABLE(xConfig XML)

INSERT @Job ( xConfig )
VALUES ( @x )

SELECT j.*
       , ca.c.value('text()[1]', 'VARCHAR(30)') AS date_val
FROM @Job AS j
CROSS APPLY j.xConfig.nodes('/SearchJobConfig/QueryString/SearchCriteria/ExpressionSet/SimpleAttributeExpression') AS ca(c)
WHERE ca.c.exist('@displayName[.= "Date"]') = 1;

Чтобы получить все в одной строке, просто сделайте это:

SELECT *
FROM 
(
    SELECT STUFF(
    (SELECT N' ' + ca.c.value('text()[1]', 'NVARCHAR(MAX)')
     FROM @Job AS j
     CROSS APPLY j.xConfig.nodes('/SearchJobConfig/QueryString/SearchCriteria/ExpressionSet/SimpleAttributeExpression') AS ca(c)
     WHERE ca.c.exist('@displayName[.= "Date"]') = 1
     FOR XML PATH(N''), TYPE ).value(N'.[1]', N'NVARCHAR(MAX)'), 1, 1, N'') 
) AS x(date_val);
Эрик Дарлинг
источник
2

Если вы хотите , значения даты в той же строке , но разные столбцы можно кромсать с помощью , nodes()чтобы получить одну строку для каждого ExpressionSetузла , а затем использовать атрибуты displayNameи searchOptionв , value()чтобы получить дату начала и окончания.

declare @x xml = '
<SearchJobConfig>
  <QueryID>1072</QueryID>
  <QueryString>
    <SearchCriteria name="Search query" >
      <ExpressionSet logicalOperator="AND">
        <SimpleAttributeExpression displayName="Date" npmPropertyId="4" searchOperation="GREATER_EQUAL" dataType="string" caseSensitive="false">2019-06-01T04:00:00</SimpleAttributeExpression>
        <SimpleAttributeExpression displayName="Date" npmPropertyId="4" searchOperation="LESS_EQUAL" dataType="string" caseSensitive="false">2019-06-13T03:59:59</SimpleAttributeExpression>
        <SimpleAttributeExpression displayName="Class" npmPropertyId="1056" searchOperation="EQUALS" dataType="int32" caseSensitive="false">65</SimpleAttributeExpression>
      </ExpressionSet>
    </SearchCriteria>
  </QueryString>
</SearchJobConfig>
';
declare @Job table(xConfig xml);
insert @Job (xConfig) values (@x);

select T.X.value('(SimpleAttributeExpression
                   [
                    @displayName = "Date" and 
                    @searchOperation = "GREATER_EQUAL"
                   ]/text())[1]', 'datetime') as date_val_start,
       T.X.value('(SimpleAttributeExpression
                   [
                    @displayName = "Date" and 
                    @searchOperation = "LESS_EQUAL"
                   ]/text())[1]', 'datetime') as date_val_end
from @Job as j
  cross apply j.xConfig.nodes('/SearchJobConfig/QueryString/
                                SearchCriteria/ExpressionSet') as T(X);

Результат:

date_val_start            date_val_end
2019-06-01 04:00:00.000   2019-06-13 03:59:59.000
Микаэль Эрикссон
источник
0

Вы говорите, что хотите извлечь несколько значений из XML, но затем указываете XPath возвращать только первое (# 1) из них:

/ SearchjobConfig / QueryString / SearchCriteria / ExpressionSet / SimpleAttributeExpression [ 1 ]
                                                                                             \___/
                                                                     Returns indexed item #1 _/

Потеряйте это условие индексации, и вы получите оба значения обратно в том порядке, в котором они отображаются во входном XML.

Дополнительное чтение: https://www.w3schools.com/xml/xpath_syntax.asp

Что касается их объединения в одну строку ... это [почти наверняка] возможно, но действительно ли это стоит усилий только для двух из них? YMMV.

Фил В.
источник