【问题标题】:XPATH Query to get data from XML stored in a SQL Server DB columnXPATH 查询以从存储在 SQL Server DB 列中的 XML 获取数据
【发布时间】:2016-02-26 07:14:37
【问题描述】:

我将 XML 数据存储在 SQL Server 数据库的一列中。

<data>
    <row>
<element name="product">Piston</element>
<element name="number">1.2</element>
    </row>
<row>
<element name="product">Piston Ring</element>
<element name="number">2</element>
    </row>
<row>
<element name="product">Piston</element>
<element name="number">1.5</element>
    </row>
</data>

有没有办法可以得到以下格式的结果?

------------------------------
Product    | Count
------------------------------
Piston     |   2
Piston Ring|   1
------------------------------

我尝试使用 Xpath,它可以计算任何东西,但不确定我是否可以按产品分组然后计算。

我正在寻找类似(在 SQL 查询中)

SELECT Product, Count(Product) FROM ABC
GROUP BY Product

【问题讨论】:

    标签: c# sql-server xml tsql xpath


    【解决方案1】:

    您不能直接在GROUP BY 中使用 XML 方法,所以我会使用 CTE。首先,您从 XML 中获取表数据,然后您可以使用 GROUP BY 执行“正常”COUNT

    DECLARE @xml XML=
    '<data>
      <row>
        <element name="product">Piston</element>
        <element name="number">1.2</element>
      </row>
      <row>
        <element name="product">Piston Ring</element>
        <element name="number">2</element>
      </row>
      <row>
        <element name="product">Piston</element>
        <element name="number">1.5</element>
      </row>
    </data>';
    
    ;WITH MyRows AS
    (
        SELECT OneRow.value('(element[@name="product"])[1]','varchar(max)') AS Product
        FROM @xml.nodes('/data/row') AS A(OneRow)
    )
    SELECT Product,COUNT(Product) AS [Count]
    FROM MyRows
    GROUP BY Product
    

    【讨论】:

    • 您好,这是预期的结果,但花费了太多时间。 (我检查了非常大的数据)。但是谢谢,它有效。
    • @Anand,您可能会考虑使用 XML 索引。我很快就回答了一个类似的问题:stackoverflow.com/q/35575990/5089204
    • @Shnugo。你能解释一下下面的工作原理吗? SELECT OneRow.value('(element[@name="product"])[1]','varchar(max)') AS Product FROM @xml.nodes('/data/row') AS A(OneRow)
    【解决方案2】:
    DECLARE @x XML=
    '<data>
      <row>
        <element name="product">Piston</element>
        <element name="number">1.2</element>
      </row>
      <row>
        <element name="product">Piston Ring</element>
        <element name="number">2</element>
      </row>
      <row>
        <element name="product">Piston</element>
        <element name="number">1.5</element>
      </row>
    </data>'
    
    SELECT val, COUNT_BIG(1)
    FROM (
        SELECT val = t.c.value('.', 'VARCHAR(100)')
        FROM @x.nodes('/data/row/element[@name="product"]') t(c)
    ) t
    GROUP BY val
    OPTION (OPTIMIZE FOR (@x = NULL))
    

    输出 -

    ------------------- --------------------
    Piston              2
    Piston Ring         1
    

    【讨论】:

    • 这太棒了!谢谢。你能解释一下最后一行吗? “选项(优化(@x = NULL))”
    • 只是一个小的优化问题,如果你期望一个非常大的 xml
    【解决方案3】:

    我会使用 CROSS APPLYtable 到 XML 列

    CREATE TABLE XMLwithOpenXML (
         id INT IDENTITY PRIMARY KEY
       , XMLData XML
       , LoadedDateTime DATETIME
    )
    GO
    
    DECLARE @xml XML = '
    <data> 
        <row>
            <element name="product">Piston</element>
            <element name="number">1.2</element>
        </row>
        <row>
            <element name="product">Piston Ring</element>
            <element name="number">2</element>
        </row>
        <row>
            <element name="product">Piston</element>
            <element name="number">1.5</element>
        </row>
    </data>'
    
    INSERT INTO XMLwithOpenXML (XMLData, LoadedDateTime)
    SELECT @xml, GETDATE()
    
    SELECT Product, COUNT(Product) AS ProdCount
    FROM (
        SELECT
             n.C.value('(element[@name="product"])[1]', 'varchar(100)') product
           , n.C.value('(element[@name="number"])[1]', 'varchar(100)') number
        FROM XMLwithOpenXML
        CROSS APPLY XMLData.nodes('/data/row') n(C)
    ) A
    GROUP BY Product
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-05
      • 2014-11-02
      • 1970-01-01
      • 2018-09-07
      • 2020-12-04
      • 2014-07-04
      • 1970-01-01
      • 2012-09-05
      相关资源
      最近更新 更多