【问题标题】:Joining nodes with the same ItemNumber into one row将具有相同 ItemNumber 的节点合并为一行
【发布时间】:2021-08-05 21:45:21
【问题描述】:

一些供应商定期发布带有商品价格的 XML 文件。文件中有两种价格:目录价格(list Price)和折扣价(discount Price)

<prices>
<price>
    <itemNumber>100</itemNumber>
    <currency>PLN</currency>
    <amount>2.98</amount>
    <type>listPrice</type>
</price>
<price>
    <itemNumber>100</itemNumber>
    <currency>PLN</currency>
    <amount>1.19</amount>
    <type>discountPrice</type>
</price>
<price>
    <itemNumber>101</itemNumber>
    <currency>PLN</currency>
    <amount>3.88</amount>
    <type>listPrice</type>
</price>
<price>
    <itemNumber>101</itemNumber>
    <currency>PLN</currency>
    <amount>2.76</amount>
    <type>discountPrice</type>
</price>
<price>
    <itemNumber>102</itemNumber>
    <currency>PLN</currency>
    <amount>4.55</amount>
    <type>listPrice</type>
</price>
<price>
    <itemNumber>102</itemNumber>
    <currency>PLN</currency>
    <amount>3.20</amount>
    <type>discountPrice</type>
</price>
<price>
    <itemNumber>103</itemNumber>
    <currency>PLN</currency>
    <amount>3.38</amount>
    <type>listPrice</type>
</price>
<price>
    <itemNumber>103</itemNumber>
    <currency>PLN</currency>
    <amount>2.90</amount>
    <type>discountPrice</type>
</price>
<price>
    <itemNumber>104</itemNumber>
    <currency>PLN</currency>
    <amount>2.98</amount>
    <type>listPrice</type>
</price>
<price>
    <itemNumber>104</itemNumber>
    <currency>PLN</currency>
    <amount>1.19</amount>
    <type>discountPrice</type>
</price>
</prices>

目前我正在将 XML 文件上传到数据库,然后我正在使用从 xml 表中获取的数据创建 tmp 表。

SELECT
@SupplierID     AS SupplierID
, a.product.query('itemNumber').value('.', 'varchar(50)')   AS SupplierCode
, a.product.query('amount').value('.', 'MONEY') AS PricePLN
, a.product.query('type').value('.', 'varchar(50)') AS NetPriceTypePLN
, GETDATE()         AS CreateDate
INTO Prices_tmp
FROM ImportedXML x(nolock)
OUTER APPLY x.xmlData.nodes('prices/price') as a(product)
where 
x.Fileid = 111

我正在努力解决的问题是如何读取 XML 以在一行中获取两个价格 喜欢:

ItemNumber | ListedPriceAmount | discountPriceAmount
100        | 2.98              | 1.19
101        | 3.88              | 2.76
102        | 4.55              | 3.20
103        | 3.38              | 2.90

你能帮帮我吗?我花了很多时间自己尝试。

【问题讨论】:

  • 是某种 XML 结构。与表中的数据是什么样的有关?样本数据和期望的结果会有所帮助。
  • 商品编号 = (string), Currency = (string), Price = (integer), Type of price = (string)
  • 见下文。您的价格是示例中的根源:docs.microsoft.com/en-us/sql/t-sql/xml/…
  • 是整个 XML 还是您有多个 &lt;price&gt; 节点,或者可能有多个 &lt;prices&gt; 节点?
  • 我有多个 节点但只有一个

标签: sql sql-server xml tsql xquery


【解决方案1】:

如果枢轴操作太难记,请尝试以下方法:

DECLARE @xml XML = '...'

WITH rs AS
(
    SELECT c.value('(itemNumber/text())[1]', 'varchar(50)') AS ItemNumber 
                , c.value('(amount/text())[1]', 'money') AS amount 
                , c.value('(type/text())[1]', 'varchar(50)') AS type 
    FROM @xml.nodes('/prices/price') AS t(c)
), sr as
(
    SELECT
            ItemNumber,
            amount ListedPriceAmount,
            0 discountPriceAmount 
    FROM rs
    where type = 'listPrice'
    union
    SELECT
            ItemNumber,
            0 ListedPriceAmount,
            amount discountPriceAmount 
    FROM rs
    where type = 'discountPrice'
)
select ItemNumber, sum(ListedPriceAmount) ListedPriceAmount, sum(discountPriceAmount) discountPriceAmount
from sr
group by ItemNumber

结果和伊扎克的回答一样。

【讨论】:

  • 像魅力一样工作!谢谢你们,Yitzhak 和 Dejan。
  • @Piotr 不要忘记为两者投票并接受 Yitzhak 的回答,并感谢您发布您的问题 :)
  • 不幸的是,我投票的声誉很低,但如果可以的话,我会投票。你们俩的解决方案解决了我的问题,非常感谢绅士们!你太棒了!
  • 啊,是的,我忘记了那部分,所以没问题我会支持你的问题:)
【解决方案2】:

请尝试以下解决方案。

提点:

  • 将适当的 XML 分解为关系/矩形格式。
  • 简单模拟 PIVOT 操作以实现所需的 输出。

SQL

DECLARE @xml XML = 
N'<prices>
    <price>
        <itemNumber>100</itemNumber>
        <currency>PLN</currency>
        <amount>2.98</amount>
        <type>listPrice</type>
    </price>
    <price>
        <itemNumber>100</itemNumber>
        <currency>PLN</currency>
        <amount>1.19</amount>
        <type>discountPrice</type>
    </price>
    <price>
        <itemNumber>101</itemNumber>
        <currency>PLN</currency>
        <amount>3.88</amount>
        <type>listPrice</type>
    </price>
    <price>
        <itemNumber>101</itemNumber>
        <currency>PLN</currency>
        <amount>2.76</amount>
        <type>discountPrice</type>
    </price>
    <price>
        <itemNumber>102</itemNumber>
        <currency>PLN</currency>
        <amount>4.55</amount>
        <type>listPrice</type>
    </price>
    <price>
        <itemNumber>102</itemNumber>
        <currency>PLN</currency>
        <amount>3.20</amount>
        <type>discountPrice</type>
    </price>
    <price>
        <itemNumber>103</itemNumber>
        <currency>PLN</currency>
        <amount>3.38</amount>
        <type>listPrice</type>
    </price>
    <price>
        <itemNumber>103</itemNumber>
        <currency>PLN</currency>
        <amount>2.90</amount>
        <type>discountPrice</type>
    </price>
    <price>
        <itemNumber>104</itemNumber>
        <currency>PLN</currency>
        <amount>2.98</amount>
        <type>listPrice</type>
    </price>
    <price>
        <itemNumber>104</itemNumber>
        <currency>PLN</currency>
        <amount>1.19</amount>
        <type>discountPrice</type>
    </price>
</prices>';

WITH rs AS
(
    SELECT c.value('(itemNumber/text())[1]', 'varchar(50)') AS ItemNumber 
        , c.value('(amount/text())[1]', 'money') AS amount 
        , c.value('(type/text())[1]', 'varchar(50)') AS type 
    FROM @xml.nodes('/prices/price') AS t(c)
)
-- simulates PIVOT operation
SELECT DISTINCT
    ItemNumber
    , MAX(IIF(type = 'listPrice', amount, 0)) OVER (PARTITION BY ItemNumber) AS ListedPriceAmount
    , MAX(IIF(type = 'discountPrice', amount, 0)) OVER (PARTITION BY ItemNumber) AS discountPriceAmount
FROM rs;

输出

+------------+-------------------+---------------------+
| ItemNumber | ListedPriceAmount | discountPriceAmount |
+------------+-------------------+---------------------+
|        100 |              2.98 |                1.19 |
|        101 |              3.88 |                2.76 |
|        102 |              4.55 |                3.20 |
|        103 |              3.38 |                2.90 |
|        104 |              2.98 |                1.19 |
+------------+-------------------+---------------------+

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    相关资源
    最近更新 更多