2012-10-27 2 views
7
declare @xmlsample xml = 
'<root> 
    <solution> 
     <solutionnumber>1</solutionnumber> 
      <productgroup> 
       <productcategory> 
        <price>100</price> 
        <title>Some product</title> 
        <tax>1</tax> 
       </productcategory> 
      </productgroup> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
    <solution> 
     <solutionnumber>2</solutionnumber> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
</root>' 

SELECT 
    --T.C.value('(./ancestor::ns1:solutionNumber)[1]', 'varchar(50)') AS solutionnumber ?? no clue 
    T.C.value('(price)[1]', 'numeric(18,2)') AS price 
    ,T.C.value('(title)[1]', 'varchar(50)') AS title 
    ,T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
FROM @xmlsample.nodes('//node()[title]') AS T(C) 

SQL Server 2008 R2에서 분쇄하려고 시도하는 XML의 표현입니다. 나는 "제목"노드를 찾고 제품 범주에 필요한 가치를 얻습니다. 이제 "솔루션 번호"를 얻으려고합니다. 그러나 특정 제품 "그룹"이 있으므로 제품 위에 하나 이상의 부모 노드가 될 수 있습니다.SQL Server .nodes() 이름으로 XML 부모 노드

부모 노드를 찾을 때까지 이름 ("solutionnumber")을 어떻게 확인합니까? 도움을 주셔서 감사합니다.

+0

잘못된 용어를 작동합니다. 그러나 여전히 "solutionnumber"를 찾고 있습니다. – duffn

답변

2

아마 내가 거꾸로 돌아갔다. 복수의 교차 적용이 그 일을 할 것입니다. 다른 포럼에 대한 도움을 주셔서 감사합니다.

SELECT 
    --T.C.value('(./ancestor::ns1:solutionNumber)[1]', 'varchar(50)') AS solutionnumber ?? no clue 
    m.c.value('(solutionnumber)[1]', 'int') as solutionnumber 
    ,T.C.value('(price)[1]', 'numeric(18,2)') AS price 
    ,T.C.value('(title)[1]', 'varchar(50)') AS title 
    ,T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
FROM @xmlsample.nodes ('//solution') as m (c) 
cross apply m.c.nodes ('.//node()[title]') as t(C) 
2

내 지식에는 직접적인 방법이 없습니다.

SELECT 
    COALESCE(T.C.value('../solutionnumber[1]', 'INT'), 
      T.C.value('../../solutionnumber[1]', 'INT'), 
      T.C.value('../../../solutionnumber[1]', 'INT')) solutionnumber, 
    T.C.value('(price)[1]', 'numeric(18,2)') AS price, 
    T.C.value('(title)[1]', 'varchar(50)') AS title, 
    T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
    FROM 
    @xmlsample.nodes('//node()[title]') AS T (C) 

주><solutionnumber 것을 정말 조상 중 하나의 형제 자매 아닌 조상 자체 그러나, 당신은 위로 당신의 방법을 검색 할 수 유착을 사용할 수 있습니다.

이 해결책을 사용하려면 미리 최대 깊이를 알아야합니다.

SELECT solutionNodes.solutionNode.value('solutionnumber[1]','INT') AS solutionnumber, 
    T.C.value('(price)[1]', 'numeric(18,2)') AS price, 
    T.C.value('(title)[1]', 'varchar(50)') AS title, 
    T.C.value('(tax)[1]', 'numeric(18,2)') AS tax 
FROM @xmlsample.nodes('//solution') AS solutionNodes (solutionNode) 
CROSS APPLY (SELECT solutionNodes.solutionNode.query('.')) solutions(solutionXML) 
CROSS APPLY solutions.solutionXML.nodes('//node()[title]') T (C) 

그것은이 <solutionnumber> 태그는 <solution> 태그의 직접적인 아이라는 사실을 사용하면 오히려 거꾸로보다 앞으로 갈 경우


또한,이 솔루션을 사용할 수 있습니다. 처음에는 모두 <solution> 태그가 있습니다. 모든 타이틀 자손보다 십자가가 적용됩니다. 노드에서 노드 함수를 사용할 수 없으므로 그 사이에 "query ('.')"계산이 있습니다.

위의 해결 방법 이외에이 태그는 <solution> 태그와 <title> 태그 사이의 거리를 처리 할 수 ​​있습니다.

1

SQL Server는 상위 항목으로 거슬러 올라가는 것을 지원하지 않으므로 XML에 내림차순으로 조상을 가리키는 포인터 인 로터리 길 caching이 있습니다.

declare @xmlsample xml = 
'<root> 
    <solution> 
     <solutionnumber>1</solutionnumber> 
      <productgroup> 
       <productcategory> 
        <price>100</price> 
        <title>Some product</title> 
        <tax>1</tax> 
       </productcategory> 
      </productgroup> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
    <solution> 
     <solutionnumber>2</solutionnumber> 
      <productcategory2> 
        <price>200</price> 
        <title>Some other product</title> 
        <tax>2</tax> 
      </productcategory2> 
    </solution> 
</root>'; 

WITH Xml_CTE AS 
(
    SELECT node.query('*') AS children, 
      node.value('fn:local-name(.)','varchar(100)') localName, 
      node.exist('title') IsTitleParent, 
      CAST(null as xml) as solution 
     FROM @xmlsample.nodes('/*') AS root(node) 
    UNION ALL 
    SELECT node.query('*') AS children, 
      node.value('fn:local-name(.)','varchar(100)') localName, 
      node.exist('title') IsTitleParent, 
      CASE WHEN node.value('fn:local-name(.)', 'varchar(100)') = 'solution' 
       THEN node.query('.') 
       ELSE solution END 
     FROM Xml_CTE x 
CROSS APPLY x.children.nodes('*') AS child(node) 
) 
SELECT solution.value('(solution/solutionnumber/text())[1]', 'int') solutionNumber 
     ,children.value('(price)[1]', 'numeric(18,2)') price 
     ,children.value('(title)[1]', 'varchar(50)') title 
     ,children.value('(tax)[1]', 'numeric(18,2)') tax 
    FROM Xml_CTE 
WHERE IsTitleParent = 1 -- matches .nodes('//node()[title]') 
OPTION (MAXRECURSION 0); 
0

이 내 부분에 ... 완벽

Declare @SomeXML XML 
SET @SomeXML = '<SomeValue>GGGG</SomeValue><SomeValue>MMMM</SomeValue><SomeValue>AAA</SomeValue>' 

select ROW_NUMBER() over (order by b), b.value('.', 'varchar(50)') 
from @SomeXML.nodes('(/SomeValue)') AS a(b)