问题描述
我正在尝试从 sql 中的价格列解析价格。我已经创建了一个函数来解析价格,但它只有在所有项目上的“所有”价格字符串都相同时才有效。我现在意识到我需要一个更强大的函数来解析多个价格配置。
I.[NAME] AS 'ITEM NAME',DBO.parsePrice(I.PRICING) AS 'ITEM PRICE'
FROM ITEM I
order by 'ITEM NAME'
这是我的函数 DBO.parsePrice
RETURNS decimal(8,2) AS
BEGIN
RETURN CAST(@in AS XML).value(N'(/prices[@type="Level"]/item[@level="A"])[1]/@price',N'DECIMAL(14,2)');
END
这是只有一个价格级别的 XML 字符串。
<prices type="Level"><item level="A" price="10.00" /></prices>
这是另一个示例,最多有 6 个不同的价格水平
<prices type="Level"><item level="A" price="10.00" /><item level="B" price="11.00" /><item level="C" price="12.00" /><item level="D" price="13.00" /><item level="E" price="14.00" /><item level="F" price="15.00" /></prices>
我的函数仅设计用于解析价格水平 (A)。为了让事情变得更加复杂,价格字符串也可以配置为不同的订单类型而不是价格水平。
<prices type="OrderType"><item level="DineIn" price="7" /><item level="TakeOut" price="8.00" /><item level="Delivery" price="" /><item level="Sale" price="" /></prices>
新函数需要处理所有这些不同的情况。理想情况下,我希望每个价格区间都有单独的列,而不是一个以逗号分隔的字段。
任何帮助将不胜感激
问候,
JC
上述 sql 查询只是发布问题的一个示例。我的实际查询是使用左连接从其他表中提取数据。
SELECT
I.[NAME] AS 'ITEM NAME',DBO.parsePrice(I.PRICING) AS 'ITEM PRICE',ML.NAME AS 'MODIFIER LIST NAME',MG.NAME AS 'MODIFIER GROUP NAME',M.NAME AS 'MODIFIER NAME',M.UPCHARGE_EXPRESSION AS UPCHARGE
FROM ITEM I
LEFT JOIN [dbo].[ITEM_MODIFIER] IM ON IM.ITEM_RECORD_KEY = I.RECORD_KEY
LEFT JOIN [dbo].[MODIFIER_LIST] ML ON ML.RECORD_KEY = IM.MODIFIER_LIST_RECORD_KEY
LEFT JOIN [dbo].[MODIFIER_GROUP] MG ON MG.MODIFIER_LIST_RECORD_KEY = ML.RECORD_KEY
LEFT JOIN [dbo].[MODIFIER] M ON M.MODIFIER_GROUP_RECORD_KEY = MG.RECORD_KEY
order by 'ITEM NAME'
解决方法
您可以创建一个 TVF 返回(级别、价格)
spring.cloud.kubernetes.config.enabled=false
并在查询中使用它
create function DBO.parsePrice(@x xml)
returns table
return
select p.n.value('@level','nvarchar(100)') level,p.n.value('@price','decimal(9,2)') price
from @x.nodes('prices/item') p(n)
编辑
在 OP 说明之后,这是 TVF 的一个版本,它为非数字的 @price 返回 0
SELECT
I.[NAME] AS 'ITEM NAME',p.*,ML.NAME AS 'MODIFIER LIST NAME',MG.NAME AS 'MODIFIER GROUP NAME',M.NAME AS 'MODIFIER NAME',M.UPCHARGE_EXPRESSION AS UPCHARGE
FROM ITEM I
LEFT JOIN [dbo].[ITEM_MODIFIER] IM ON IM.ITEM_RECORD_KEY = I.RECORD_KEY
LEFT JOIN [dbo].[MODIFIER_LIST] ML ON ML.RECORD_KEY = IM.MODIFIER_LIST_RECORD_KEY
LEFT JOIN [dbo].[MODIFIER_GROUP] MG ON MG.MODIFIER_LIST_RECORD_KEY = ML.RECORD_KEY
LEFT JOIN [dbo].[MODIFIER] M ON M.MODIFIER_GROUP_RECORD_KEY = MG.RECORD_KEY
CROSS APPLY DBO.parsePrice(I.PRICING) p
order by 'ITEM NAME',p.Level
,
我已将 Serg 解决方案标记为正确的解决方案,即使我必须进行一些更改才能产生我们正在寻找的结果,而不会出现数据类型转换错误。这是我正在使用的完整解决方案。
SQL 查询
SELECT
I.[NAME] AS 'ITEM NAME',ic.NAME AS 'ITEM CATEGORY',M.UPCHARGE_EXPRESSION AS UPCHARGE
FROM ITEM I
LEFT JOIN [dbo].[ITEM_MODIFIER] IM ON IM.ITEM_RECORD_KEY = I.RECORD_KEY
LEFT JOIN [DBO].[ITEM_CATEGORY] IC ON IC.RECORD_KEY = I.ITEM_CATEGORY_RECORD_KEY
LEFT JOIN [dbo].[MODIFIER_LIST] ML ON ML.RECORD_KEY = IM.MODIFIER_LIST_RECORD_KEY
LEFT JOIN [dbo].[MODIFIER_GROUP] MG ON MG.MODIFIER_LIST_RECORD_KEY = ML.RECORD_KEY
LEFT JOIN [dbo].[MODIFIER] M ON M.MODIFIER_GROUP_RECORD_KEY = MG.RECORD_KEY
CROSS APPLY DBO.parsePrice(I.PRICING) p
/*where ml.name is not null*/
order by 'ITEM CATEGORY','ITEM NAME',P."Price TYPE",P."Price LEVEL"
Tabled_Valued 函数
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE function [dbo].[parsePrice](@x xml)
returns table
return
select "PRICE TYPE","PRICE LEVEL",coalesce(try_cast("Item Price" as decimal(9,2)),0) "ITEM PRICE"
from (
select t.n.value('@type','varchar(100)') "PRICE TYPE",p.n.value('@level','varchar(100)') "PRICE LEVEL",'nvarchar(50)') "ITEM PRICE"
from @x.nodes('//prices') t(n),@x.nodes('prices/item') p(n)
) t