SQLServerCentral is supported by Red Gate Software Ltd.
 
Log in  ::  Register  ::  Not logged in
Search:  
 
 

Pro SQL Server XML

Add to Technorati Favorites Add to Google
 

Unmatched Nodes in XQuery

By Michael Coles in Pro SQL Server XML | 02-25-2008 12:53 AM | Categories: Filed under: , , , , , , ,
Rating: (not yet rated) |  Discuss | 5,459 Reads | 691 Reads in Last 30 Days |no comments

In a previous post I talked about performing "inner joins" in XQuery. The basic idea is that the inner join is simply a special case of a Cartesian product, or "cross join".  In this post I'm going to briefly look at another common SQL-style join condition that can be duplicated to some degree in XQuery. Specifically I'm going to give an example of a retrieving nodes from a tuple stream that don't match the nodes in a second tuple stream.

In this post we'll duplicate about 50% of the SQL "left outer join" functionality. For those who aren't familiar with SQL left outer joins, they can be thought of as an inner join between two tables unioned together with the rows of the left-hand table that have no corresponding rows in the right-hand table.

For this example I'm going to borrow some slightly modified XML data from the previous post:

DECLARE @xml xml;
-- Create sample XML document
SET @xml = N'<authors>
  <author id = "1">Fabio Claudio Ferracchiati</author>
  <author id = "2">Hugo Kornelis</author>
  <author id = "3">Rob Walters</author>
  <author id = "4">Lara Rubbelke</author>
  <author id = "5">Adam Machanic</author>
  <author id = "6">Michael Coles</author>
  <author id = "7">Robin Dewson</author>
  <author id = "8">Jan D. Narkiewicz</author>
  <author id = "9">Robert Rae</author>
</authors>
<books>
  <book title = "Pro T-SQL 2005 Programmer&apos;s Guide">
    <isbn>159059794X</isbn>
    <author>6</author>
  </book>
  <book title = "Accelerated SQL Server 2008">
    <isbn>1590599691</isbn>
    <author>3</author>
    <author>6</author>
    <author>7</author>
    <author>1</author>
    <author>8</author>
    <author>9</author>
  </book>
  <book title = "Pro SQL Server 2008 XML">
    <isbn>1590599837</isbn>
    <author>6</author>
  </book>
</books>'
;
-- Perform outer join
SELECT @xml.query('for $author in /authors/author
  where fn:empty($author[@id = /books/book/author])
  return <author> { $author } </author>'
);

This sample is available as a download file here.

The XML data consists of a list of authors and a list of books. The query uses a FLWOR expression to retrieve all authors who don't have a corresponding book node. Here's how it works:

  1. The for clause binds the tuple stream /authors/author to the $author variable.  By "binding the tuple stream", I mean that every author node is assigned to the $author variable in turn. For those from a C# background you can think of this as a foreach loop over the XML nodes specified by the path expression.
  2. The where clause uses the fn:empty() function to determine if the id attribute of the current $author node exists in the /books/book/author node sequence. Basically we're checking to see if the current author's ID # is assigned to any given book or not. If not, the fn:empty() function returns true.
  3. The return clause uses XML construction to build an <author> element for every author that meets the where clause condition (e.g., no matching book).

The results are shown below:

<author>
 
<author id="2">Hugo Kornelis</author>
</
author>
<
author>
  <
author id="4">Lara Rubbelke</author>
</author>
<
author>
 
<author id="5">Adam Machanic</author>
</author>

As you can see, the three authors with id's of (2, 4, 5) were returned because they have no corresponding book nodes in the XML data. This technique, combined with the previously discussed inner join technique, can be used to simulate SQL style outer joins in XQuery.

Add to Technorati Favorites 

Comments
There are no comments on this post
Leave a Comment
Only members of SQLServerCentral may leave comments. Register now for your free account or Sign-In if you are already a member.