将具有相同 ItemNumber 的节点加入一行
Joining nodes with the same ItemNumber into one row
一些供应商定期发布包含商品价格的 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 table.[=13 中获取的数据创建 tmp table =]
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 粉碎成 relational/rectangular 格式。
- 简单模拟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 |
+------------+-------------------+---------------------+
如果主元运算太难记不住,试试这个:
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 的回答相同。
一些供应商定期发布包含商品价格的 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 table.[=13 中获取的数据创建 tmp table =]
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 粉碎成 relational/rectangular 格式。
- 简单模拟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 |
+------------+-------------------+---------------------+
如果主元运算太难记不住,试试这个:
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 的回答相同。