Querying against XML

  • Hello all,

    I have the following xml and I'm trying to build a query that will output ids of both familyid element and memberid element under each family node. Is it possible using sql?

    DECLARE @XML XML;

    SET @XML =
     N'
    <root>
    <families>
    <family>
    <Familyid>F1</Familyid>
    <FamilyMemberDetails>
     <Members>
      <Familyid>F1</Familyid>
      <Id>M1</Id>
      <FirstName>John</FirstName>
     </Members>
     <Members>
      <Familyid>F1</Familyid>
      <Id>M2</Id>
      <FirstName>Lewis</FirstName>
     </Members>
    </FamilyMemberDetails>
    </family>
    <family>
    <Familyid>F2</Familyid>
    <FamilyMemberDetails>
     <Members>
      <Familyid>F2</Familyid>
      <Id>M1</Id>
      <FirstName>Chris</FirstName>
     </Members>
     <Members>
      <Familyid>F2</Familyid>
      <Id>M2</Id>
      <FirstName>Linda</FirstName>
     </Members>
    </FamilyMemberDetails>
    </family>
    </families>
    </root>';

    SELECT @XML;

    FamilyID MemberID
    -----------------------
    F1 M1
    -----------------------
    F1 M2
    -----------------------
    F2 M1
    -----------------------
    F2 M2
    -----------------------

  • Two methods which return the same results
    😎
    DECLARE @XML XML;

    SET @XML =
    N'<root>
    <families>
      <family>
      <Familyid>F1</Familyid>
      <FamilyMemberDetails>
       <Members>
        <Familyid>F1</Familyid>
        <Id>M1</Id>
        <FirstName>John</FirstName>
       </Members>
       <Members>
        <Familyid>F1</Familyid>
        <Id>M2</Id>
        <FirstName>Lewis</FirstName>
       </Members>
      </FamilyMemberDetails>
      </family>
      <family>
      <Familyid>F2</Familyid>
      <FamilyMemberDetails>
       <Members>
        <Familyid>F2</Familyid>
        <Id>M1</Id>
        <FirstName>Chris</FirstName>
       </Members>
       <Members>
        <Familyid>F2</Familyid>
        <Id>M2</Id>
        <FirstName>Linda</FirstName>
       </Members>
      </FamilyMemberDetails>
      </family>
    </families>
    </root>';
    ---------------------------------------------------------------------------------------
    SELECT
      FAMILY.DATA.value('(Familyid/text())[1]','VARCHAR(10)') AS FamilyID
     ,FAMILY.DATA.value('(Id/text())[1]'  ,'VARCHAR(10)') AS MemberID
    FROM @XML.nodes('root/families/family/FamilyMemberDetails/Members') AS FAMILY(DATA);
    ---------------------------------------------------------------------------------------
    SELECT
      FAMILY.DATA.value('(Familyid/text())[1]' ,'VARCHAR(10)') AS FamilyID
     ,MEMBERS.DATA.value('(Id/text())[1]'  ,'VARCHAR(10)') AS MemberID
    FROM @XML.nodes('root/families/family') AS FAMILY(DATA)
    CROSS APPLY FAMILY.DATA.nodes('FamilyMemberDetails/Members') MEMBERS(DATA);
    ---------------------------------------------------------------------------------------

    Output
    FamilyID   MemberID
    ---------- ----------
    F1         M1
    F1         M2
    F2         M1
    F2         M2


  • Eirikur Eiriksson - Saturday, February 18, 2017 12:58 AM

    Two methods which return the same results
    😎

    Hello Eirikur,
    Both methods deliver the same result (for the example code), the second script is longer and looks more complex (to me). So can you explain why the second method ?

    I am trying to learn from you anwser, thanks.
    Ben

  • Eirikur Eiriksson - Saturday, February 18, 2017 12:58 AM

    Two methods which return the same results
    😎
    DECLARE @XML XML;

    SET @XML =
    N'<root>
    <families>
      <family>
      <Familyid>F1</Familyid>
      <FamilyMemberDetails>
       <Members>
        <Familyid>F1</Familyid>
        <Id>M1</Id>
        <FirstName>John</FirstName>
       </Members>
       <Members>
        <Familyid>F1</Familyid>
        <Id>M2</Id>
        <FirstName>Lewis</FirstName>
       </Members>
      </FamilyMemberDetails>
      </family>
      <family>
      <Familyid>F2</Familyid>
      <FamilyMemberDetails>
       <Members>
        <Familyid>F2</Familyid>
        <Id>M1</Id>
        <FirstName>Chris</FirstName>
       </Members>
       <Members>
        <Familyid>F2</Familyid>
        <Id>M2</Id>
        <FirstName>Linda</FirstName>
       </Members>
      </FamilyMemberDetails>
      </family>
    </families>
    </root>';
    ---------------------------------------------------------------------------------------
    SELECT
      FAMILY.DATA.value('(Familyid/text())[1]','VARCHAR(10)') AS FamilyID
     ,FAMILY.DATA.value('(Id/text())[1]'  ,'VARCHAR(10)') AS MemberID
    FROM @XML.nodes('root/families/family/FamilyMemberDetails/Members') AS FAMILY(DATA);
    ---------------------------------------------------------------------------------------
    SELECT
      FAMILY.DATA.value('(Familyid/text())[1]' ,'VARCHAR(10)') AS FamilyID
     ,MEMBERS.DATA.value('(Id/text())[1]'  ,'VARCHAR(10)') AS MemberID
    FROM @XML.nodes('root/families/family') AS FAMILY(DATA)
    CROSS APPLY FAMILY.DATA.nodes('FamilyMemberDetails/Members') MEMBERS(DATA);
    ---------------------------------------------------------------------------------------

    Output
    FamilyID   MemberID
    ---------- ----------
    F1         M1
    F1         M2
    F2         M1
    F2         M2


    ='font-size:9.0pt;mso-bidi-font-size:11.0pt;line-height:107%;font-family:"courier>

    Thanks..it worked!

  • ben.brugman - Tuesday, February 21, 2017 2:03 AM

    Eirikur Eiriksson - Saturday, February 18, 2017 12:58 AM

    Two methods which return the same results
    😎

    Hello Eirikur,
    Both methods deliver the same result (for the example code), the second script is longer and looks more complex (to me). So can you explain why the second method ?

    I am trying to learn from you anwser, thanks.
    Ben

    The difference is that the second method goes first on the Family node level and then for each of those it iterates through all the member child nodes. This is useful if i.e. the family ID is only present at the parent level and not the child level. Performance wise those two methods are almost identical.
    😎

  • Eirikur Eiriksson - Tuesday, February 21, 2017 9:03 AM

    The difference is that the second method goes first on the Family node level and then for each of those it iterates through all the member child nodes. This is useful if i.e. the family ID is only present at the parent level and not the child level. Performance wise those two methods are almost identical.
    😎

    Thanks, this is usefull to know and applicable for many other examples. Thanks for extending the anwser beyond the question, usefull.

    Thanks,
    Ben

Viewing 6 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic. Login to reply