【问题标题】:How to get all elements dynamically without knowing their number如何在不知道其数量的情况下动态获取所有元素
【发布时间】:2020-03-13 20:31:09
【问题描述】:

我有一个可能有多个签名元素的 xml。我不知道每个根的签名元素的数量,但我需要按此元素分组,以便为​​每个根元素获得一行。

您认为使用价值方法可行吗? 我已阅读 (Getting nth Element from last in a xml in Sql Server) 如何确定元素数量,但不允许在值方法中使用范围。

这是我的代码:

            declare @xml as xml ='<root>
                <Row>
                    <proceeding>
                        <signatures>XII GU 609/18</signatures>
                        <signatures>XII GUp 392/18</signatures>
                        <commissioner_name></commissioner_name>
                        <court_department>XII Wydział Gospodarczy</court_department>
                        <administrator_function>syndyk</administrator_function>
                        <court_name>Sąd Rejonowy w Gliwicach</court_name>
                        <administrator_name></administrator_name>
                        <commissioner_deputy_name />
                        <administrator_licence_number>920</administrator_licence_number>
                    </proceeding>
                    <msig_entry>
                        <chapter>0</chapter>
                        <issue_date>2019-11-15</issue_date>
                        <url>http://www.imsig.pl/pozycja/2019/221/58729</url>
                        <section>3</section>
                        <sequential_number />
                        <signature>BMSiG-58674/2019</signature>
                        <position_number>58729</position_number>
                        <yearly_number>221</yearly_number>
                    </msig_entry>
                    <id>BMSiG-58674/2019</id>
                    <order>
                        <order_date />
                        <expiration_period>14</expiration_period>
                        <expiration_date>2019-11-29</expiration_date>
                    </order>
                </Row>
            </root>'

            select  
            isnull(a.x.value('(entity/info/cleaned_name)[1]','varchar(max)'),'') as 'Nazwa podmiotu'
            ,isnull(a.x.value('(entity/info/first_name)[1]','varchar(max)'),'') as 'Imię'
            ,isnull(a.x.value('(entity/info/last_name)[1]','varchar(max)'),'') as 'Nazwisko'
            ,isnull(a.x.value('(entity/info/legal_form)[1]','varchar(max)'),'') as 'Forma prawna'
            ,isnull(a.x.value('(entity/info/ownership_type)[1]','varchar(max)'),'') as 'Forma własności'
            ,isnull(a.x.value('(entity/info/commencement_date)[1]','date'),'') as 'Data rozpoczęcia działalności'

            ,isnull(a.x.value('(entity/address/zip_code)[1]','varchar(255)'),'')+' '+isnull(a.x.value('(entity/address/town)[1]','varchar(255)'),'')
            +' '+isnull(a.x.value('(entity/address/street)[1]','varchar(255)'),'')+' '+ISNULL(a.x.value('(entity/address/house_number)[1]','varchar(255)'),'')
            +case when ISNULL(a.x.value('(entity/address/flat_number)[1]','varchar(255)'),'')<>'' then +'/'+a.x.value('(entity/address/flat_number)[1]','varchar(255)')
            else '' end as Adres

            ,isnull(a.x.value('(proceeding/court_name)[1]','varchar(max)'),'') as 'Nazwa sądu'
            ,isnull(a.x.value('(proceeding/court_department)[1]','varchar(max)'),'') as 'Nazwa wydziału'
            ,isnull(a.x.value('(proceeding/signatures)[1]','varchar(max)'),'') as 'Sygnatura'  --grupowanie!
            ,isnull(a.x.value('(proceeding/commissioner_name)[1]','varchar(max)'),'') as 'Sędzia komisarz'
            ,isnull(a.x.value('(proceeding/commissioner_deputy_name)[1]','varchar(max)'),'') as 'Zastępca sędziego komisarza'
            ,isnull(a.x.value('(proceeding/administrator_name)[1]','varchar(max)'),'') as 'Nadzorca w postępowaniu'
            ,isnull(a.x.value('(proceeding/administrator_function)[1]','varchar(max)'),'') as 'Funkcja nadzorcy'

            ,isnull(a.x.value('(order/order_date)[1]','date'),'') as 'Data wydania postanowienia'
            ,isnull(a.x.value('(order/expiration_period)[1]','varchar(20)'),'') as 'Okres do działania (w dniach)'
            ,isnull(a.x.value('(order/expiration_date)[1]','date'),'') as 'Koniec okresu do działania'

            ,isnull(a.x.value('(msig_entry/chapter)[1]','varchar(max)'),'') as 'Rozdział MSiG'
            ,isnull(a.x.value('(msig_entry/section)[1]','varchar(max)'),'') as 'Sekcja MSiG'
            ,isnull(a.x.value('(msig_entry/signature)[1]','varchar(max)'),'') as 'Sygnatura ogłoszenia'
            ,isnull(a.x.value('(msig_entry/issue_date)[1]','date'),'') as 'Data publikacji ogłoszenia w MSiG'

            ,isnull(a.x.value('(content/text)[1]','varchar(max)'),'') as 'Treść ogłoszenia'

            from @xml.nodes('/root/Row') as a(x)

我想要的结果:

【问题讨论】:

  • 三个提示:感谢可执行示例,这是一个很大的帮助,但下次您可能会将其减少到所需的最低限度。第二:请添加预期的输出。您的问题尚不完全清楚...第三:请使用您的 RDBMS(供应商 和版本)进行标记。 [tsql] 和代码指向 [sql-server],但 XML 支持是高度特定于产品的。
  • @Shnugo,感谢您的准确观察,实际上。我刚刚编辑了我的问题。

标签: xml tsql sql-server-2012


【解决方案1】:

不跨越技术边界的更短的解决方案可能是这样的:

        ,isnull(STUFF(
                a.x.query('for $s in proceeding/signatures
                           return <x>{concat(",",$s)}</x>')
                   .value('.','varchar(max)'),1,1,''),'') as 'Sygnatura'  --grupowanie!

简而言之:

我们使用.query() 重新格式化XML 片段a.x,以某种方式返回每个签名前面带有一个逗号。

现在我们可以将.value() 与简单'.' 的XPath 一起使用。这将在一个块中读取所有内容

最后我们需要STUFF 去掉前面的逗号。

更新

实际上最短的方法是这样的:

,isnull(a.x.query('data(proceeding/signatures)').value('.','varchar(max)'),'') as 'Sygnatura'  --grupowanie!

XQuery 函数data() 将隐式连接元素并返回以空格分隔的元素。我希望有一个参数来定义分隔符,但这是 - 为什么永远 - 不可能。您的问题是,您的签名在内部包含空白。所以这可能对你不起作用。

【讨论】:

  • 好东西,我这边+1!
  • Shnugo 太棒了!你能告诉我 $s 合成器指的是什么吗?
  • @Arkadiusz,除了 XQuery 明显构建的问题之外,XQuery 还提供了一些字符串操作的技巧。直接回答您的问题:$@ 中的T-SQL 相同:它标记了一个变量。在这种情况下,我们遍历所有&lt;signatures&gt;。每个节点都分配给$s。有了这个,我们继续下面。查找有关 XQuery-FLWOR 的详细信息here
  • @Shnugo,谢谢,它看起来很有用,所以我要熟悉一下这些东西。
【解决方案2】:

请尝试以下方法。

SQL

DECLARE @xml AS XML
= '<root>
        <Row>
            <proceeding>
                <signatures>XII GU 609/18</signatures>
                <signatures>XII GUp 392/18</signatures>
                <commissioner_name></commissioner_name>
                <court_department>XII Wydział Gospodarczy</court_department>
                <administrator_function>syndyk</administrator_function>
                <court_name>Sąd Rejonowy w Gliwicach</court_name>
                <administrator_name></administrator_name>
                <commissioner_deputy_name />
                <administrator_licence_number>920</administrator_licence_number>
            </proceeding>
            <msig_entry>
                <chapter>0</chapter>
                <issue_date>2019-11-15</issue_date>
                <url>http://www.imsig.pl/pozycja/2019/221/58729</url>
                <section>3</section>
                <sequential_number />
                <signature>BMSiG-58674/2019</signature>
                <position_number>58729</position_number>
                <yearly_number>221</yearly_number>
            </msig_entry>
            <entity>
                <info>
                    <first_name></first_name>
                    <last_name></last_name>
                    <legal_form>osoby fizyczne</legal_form>
                    <commencement_date>1954-12-09</commencement_date>
                    <cleaned_name></cleaned_name>
                    <primary_business />
                    <ownership_type>własność</ownership_type>
                </info>
                <address>
                    <town>Jastrzębie-Zdrój</town>
                    <gmina>Jastrzębie-Zdrój</gmina>
                    <house_number />
                    <flat_number />
                    <state>śląskie</state>
                    <street />
                    <post_office>Jastrzębie-Zdrój</post_office>
                    <powiat>Jastrzębie-Zdrój</powiat>
                    <zip_code />
                </address>
            </entity>
            <id>BMSiG-58674/2019</id>
            <order>
                <order_date />
                <expiration_period>14</expiration_period>
                <expiration_date>2019-11-29</expiration_date>
            </order>
        </Row>
    </root>';

DECLARE @separator CHAR(1) = ',';

SELECT ISNULL(x.value('(entity/info/cleaned_name)[1]', 'varchar(max)'), '') AS 'Nazwa podmiotu',
       ISNULL(x.value('(entity/info/first_name)[1]', 'varchar(max)'), '') AS 'Imię',
       ISNULL(x.value('(entity/info/last_name)[1]', 'varchar(max)'), '') AS 'Nazwisko',
       ISNULL(x.value('(entity/info/legal_form)[1]', 'varchar(max)'), '') AS 'Forma prawna',
       ISNULL(x.value('(entity/info/ownership_type)[1]', 'varchar(max)'), '') AS 'Forma własności',
       ISNULL(x.value('(entity/info/commencement_date)[1]', 'date'), '') AS 'Data rozpoczęcia działalności',
       ISNULL(x.value('(entity/address/zip_code)[1]', 'varchar(255)'), '') + ' '
       + ISNULL(x.value('(entity/address/town)[1]', 'varchar(255)'), '') + ' '
       + ISNULL(x.value('(entity/address/street)[1]', 'varchar(255)'), '') + ' '
       + ISNULL(x.value('(entity/address/house_number)[1]', 'varchar(255)'), '')
       + CASE
             WHEN ISNULL(a.x.value('(entity/address/flat_number)[1]', 'varchar(255)'), '') <> '' THEN
                 +'/' + a.x.value('(entity/address/flat_number)[1]', 'varchar(255)')
             ELSE
                 ''
         END AS Adres,
       ISNULL(x.value('(proceeding/court_name)[1]', 'varchar(max)'), '') AS 'Nazwa sądu',
       ISNULL(x.value('(proceeding/court_department)[1]', 'varchar(max)'), '') AS 'Nazwa wydziału',

    -- grupowanie by Sygnatura
    (SELECT STUFF((SELECT @separator + CAST([Sygnatura] AS VARCHAR(30)) AS [text()]
          FROM (
                SELECT ISNULL(c.value('(./text())[1]', 'VARCHAR(MAX)'), '') AS [Sygnatura]
                FROM @xml.nodes('/root/Row/proceeding/signatures') AS t(c)
          ) AS rs
          FOR XML PATH('')), 1, 1, NULL)) AS [Sygnatura_List],

       ISNULL(x.value('(proceeding/commissioner_name)[1]', 'varchar(max)'), '') AS 'Sędzia komisarz',
       ISNULL(x.value('(proceeding/commissioner_deputy_name)[1]', 'varchar(max)'), '') AS 'Zastępca sędziego komisarza',
       ISNULL(x.value('(proceeding/administrator_name)[1]', 'varchar(max)'), '') AS 'Nadzorca w postępowaniu',
       ISNULL(x.value('(proceeding/administrator_function)[1]', 'varchar(max)'), '') AS 'Funkcja nadzorcy',
       ISNULL(x.value('(order/order_date)[1]', 'date'), '') AS 'Data wydania postanowienia',
       ISNULL(x.value('(order/expiration_period)[1]', 'varchar(20)'), '') AS 'Okres do działania (w dniach)',
       ISNULL(x.value('(order/expiration_date)[1]', 'date'), '') AS 'Koniec okresu do działania',
       ISNULL(x.value('(msig_entry/chapter)[1]', 'varchar(max)'), '') AS 'Rozdział MSiG',
       ISNULL(x.value('(msig_entry/section)[1]', 'varchar(max)'), '') AS 'Sekcja MSiG',
       ISNULL(x.value('(msig_entry/signature)[1]', 'varchar(max)'), '') AS 'Sygnatura ogłoszenia',
       ISNULL(x.value('(msig_entry/issue_date)[1]', 'date'), '') AS 'Data publikacji ogłoszenia w MSiG',
       ISNULL(x.value('(content/text)[1]', 'varchar(max)'), '') AS 'Treść ogłoszenia'
FROM @xml.nodes('/root/Row') AS a(x);

输出(为清楚起见缩写)

+--------------------------+-------------------------+------------------------------+
|        Nazwa sądu        |     Nazwa wydziału      |        Sygnatura_List        |
+--------------------------+-------------------------+------------------------------+
| Sad Rejonowy w Gliwicach | XII Wydzial Gospodarczy | XII GU 609/18,XII GUp 392/18 |
+--------------------------+-------------------------+------------------------------+

【讨论】:

  • Yitzhak,因为你是 FLWOR 的朋友,我刚刚在下面发了一堆 FLWOR :-) +1 从我这边得到这个好的答案。
  • Shnugo,大声笑,我在我的机器上做了同样的事情,但不想发布它并混淆 Arkadiusz。你和我,我们在同一页上。 :)
猜你喜欢
  • 2017-05-01
  • 2012-04-17
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多