在SQL Server中查找第n个模式

时间:2015-01-26 13:13:39

标签: sql-server sql-server-2008-r2

我需要在第二次出现的<spot><Points>标签中提取值。我尝试了使用子字符串和模式索引函数的不同方法,但没有成功。

<?xml version="1.0" encoding="utf-16"?>
<FSSTradeDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Markup>
        <Price>
            <PriceType>A</PriceType>
            <Wholesale>1.2772663500412138</Wholesale>
            <WholesaleRateComposition>
                <Rate>
                    <Terms>A</Terms>
                    <CurPair>GBP-USD</CurPair>
                    <Spot>1.61125</Spot>
                    <Points>157.95740000000168</Points>
                    <Forward>1.6270457400000002</Forward>
                </Rate>
                <Rate>
                    <Terms>A</Terms>
                    <CurPair>GBP-EUR</CurPair>
                    <Spot>1.2648663500412138</Spot>
                    <Points>124</Points>
                    <Forward>1.2772663500412138</Forward>
                </Rate>
                <Rate>
                    <Terms>A</Terms>
                    <CurPair>EUR-USD</CurPair>
                    <Spot>1.27385</Spot>
                    <Points>0</Points>
                    <Forward>1.27385</Forward>
                </Rate>
                <RateStates>
                    <ContractCounter>DEf</ContractCounter>
                    <ContractVia>Dff</ContractVia>
                    <CounterVia>DDf</CounterVia>
                </RateStates>
            </WholesaleRateComposition>
            <Markup>12</Markup>
            <Quote>1.27846635004121</Quote>
        </Price>
        <Profit>
            <Amount>1.53</Amount>
            <SpotRate>1.27385</SpotRate>
            <Terms>A</Terms>
            <NativeAmount>1.2000000000000455</NativeAmount>
            <NativeCurrency>EUR</NativeCurrency>
        </Profit>
    </Markup>
    <WholesaleRiskTransfer>
        <Transfer>No</Transfer>
    </WholesaleRiskTransfer>
</FSSTradeDetails>

这是我试过的查询:

SELECT 
   convert(DECIMAL(38, 8), 
           substring(DETAILS, CASE 
                                 WHEN PATINDEX('%<Spot>%', DETAILS) + 6 = 6
                                 THEN 0
                                 ELSE PATINDEX('%<Spot>%', DETAILS) + 6
                               END, 
   (PATINDEX('%</Spot>%', DETAILS) - (CASE 
                        WHEN PATINDEX('%<Spot>%', DETAILS) + 6 = 6
                            THEN 0
                        ELSE PATINDEX('%<Spot>%', DETAILS) + 6
                        END
                    )
                ))) AS [Spot Rate]

感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

我建议你使用XML方法完成这项任务:

DECLARE @xml xml = N'<FSSTradeDetails xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Markup><Price><PriceType>A</PriceType><Wholesale>1.2772663500412138</Wholesale><WholesaleRateComposition><Rate><Terms>A</Terms>
<CurPair>GBP-USD</CurPair><Spot>1.61125</Spot><Points>157.95740000000168</Points><Forward>1.6270457400000002</Forward></Rate><Rate><Terms>A</Terms>
<CurPair>GBP-EUR</CurPair><Spot>1.2648663500412138</Spot><Points>124</Points><Forward>1.2772663500412138</Forward></Rate><Rate><Terms>A</Terms>
<CurPair>EUR-USD</CurPair><Spot>1.27385</Spot><Points>0</Points><Forward>1.27385</Forward></Rate><RateStates><ContractCounter>DEf</ContractCounter>
<ContractVia>Dff</ContractVia><CounterVia>DDf</CounterVia></RateStates></WholesaleRateComposition><Markup>12</Markup><Quote>1.27846635004121</Quote>
</Price><Profit><Amount>1.53</Amount><SpotRate>1.27385</SpotRate><Terms>A</Terms><NativeAmount>1.2000000000000455</NativeAmount>
<NativeCurrency>EUR</NativeCurrency></Profit></Markup><WholesaleRiskTransfer><Transfer>No</Transfer></WholesaleRiskTransfer></FSSTradeDetails>'

SELECT
      WholesaleRateComposition.value('Rate[2]/Spot[1]', 'decimal(38, 20)') AS SecondSpot
    , WholesaleRateComposition.value('Rate[2]/Points[1]', 'decimal(38, 20)') AS SecondPoints
FROM @xml.nodes('/FSSTradeDetails/Markup/Price/WholesaleRateComposition') AS Price(WholesaleRateComposition);

要获得第n次出现,您需要使用动态SQL,因为序数必须是静态的:

DECLARE @Occurance nvarchar(5) = '3';
DECLARE @Sql nvarchar(MAX) = 
'SELECT
      WholesaleRateComposition.value(''Rate[' + @Occurance + ']/Spot[1]'', ''decimal(38, 20)'') AS SecondSpot
    , WholesaleRateComposition.value(''Rate[' + @Occurance + ']/Points[1]'', ''decimal(38, 20)'') AS SecondPoints
FROM @xml.nodes(''/FSSTradeDetails/Markup/Price/WholesaleRateComposition'') AS Price(WholesaleRateComposition);'

EXEC sp_executesql @Sql, N'@xml xml', @xml = @xml;