Pertanyaan Kueri XML

8

Saya mencoba membuat kueri SQL untuk mendapatkan nilai "DATE" dari SQL XML berikut:

ScreenShot

Saya sudah mencoba sesuatu seperti ini tapi saya rasa saya tidak mengerti konsepnya.

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

Berikut ini adalah XML sebagai teks:

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

Output yang diharapkan adalah Tanggal:

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

dan apa yang diperlukan untuk mendapatkan hasil pada baris yang sama .. contoh:

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

Saya menggunakan SQL Server 2012 Enterprise Edition.

John
sumber

Jawaban:

8

Apakah ini membuat Anda mendapatkan apa yang Anda inginkan?

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;

Untuk mendapatkan semuanya dalam satu baris, lakukan ini:

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);
Erik Darling
sumber
2

Jika Anda ingin nilai tanggal pada baris yang sama tetapi kolom yang berbeda Anda dapat rusak menggunakan nodes()untuk mendapatkan satu baris per ExpressionSetnode dan kemudian menggunakan atribut displayNamedan searchOptiondi value()untuk mendapatkan mulai dan tanggal akhir.

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

Hasil:

date_val_start            date_val_end
2019-06-01 04:00:00.000   2019-06-13 03:59:59.000
Mikael Eriksson
sumber
0

Anda mengatakan bahwa Anda ingin mengambil beberapa nilai dari XML, tetapi kemudian menginstruksikan XPath Anda untuk mengembalikan hanya yang pertama (# 1) dari mereka:

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

Kalah klausa pengindeksan ini dan Anda akan mendapatkan kedua nilai kembali, dalam urutan yang muncul dalam input XML.

Bacaan lebih lanjut: https://www.w3schools.com/xml/xpath_syntax.asp

Sejauh membuat mereka menjadi satu baris ... itu [hampir pasti] mungkin, tetapi apakah itu benar-benar sepadan dengan usaha hanya dua dari mereka? YMMV.

Phill W.
sumber