Question de requête XML


8

J'essaie de générer une requête SQL pour obtenir les valeurs "DATE" du XML XML suivant:

Capture d'écran

J'ai essayé quelque chose comme ça, mais je ne pense pas que je comprends les concepts.

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

Voici le XML sous forme de texte:

<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>

La sortie attendue serait les dates:

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

et que faudrait-il pour obtenir les résultats sur la même ligne. exemple:

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

J'utilise SQL Server 2012 Enterprise Edition.

Réponses:


8

Est-ce que cela vous donne ce que vous voulez?

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;

Pour obtenir tout sur une seule ligne, procédez comme suit:

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

Si vous voulez que les valeurs de date dans la même ligne , mais différentes colonnes que vous pouvez déchiquettent à l' aide nodes()pour obtenir une ligne par ExpressionSetnœud, puis utiliser des attributs displayNameet searchOptionen value()obtenir de début et de fin.

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);

Résultat:

date_val_start            date_val_end
2019-06-01 04:00:00.000   2019-06-13 03:59:59.000

0

Vous dites que vous souhaitez récupérer plusieurs valeurs à partir du XML, mais vous demandez ensuite à votre XPath de n'en renvoyer que la première (# 1):

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

Si vous perdez cette clause d'indexation, vous récupérerez les deux valeurs dans l'ordre dans lequel elles apparaissent dans le XML d'entrée.

Pour en savoir plus: https://www.w3schools.com/xml/xpath_syntax.asp

En ce qui concerne leur mise sur une seule ligne ... c'est [presque certainement] peut-être, mais cela vaut-il vraiment l'effort pour seulement deux d'entre eux? YMMV.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.