XQuery Node Order: Compare Source Document Positions

I use XQuery node order to compare positions in a source document. The << and >> operators ask which node comes before or after another. They don’t sort the elements’ text or compare their business values.

Two blank upright books stand behind a flat sage-green book topped by a small brass ring.
Two upright books behind a flat one, like nodes placed one after another.

Make source order visible

The fixed document places zebra first, apple second and middle third. This deliberately differs from a natural alphabetical arrangement. The first two text columns remain visible beside the positional comparisons.

Each operand selects one Item node from the same Doc value. Parenthesized paths with positional predicates make that selection explicit. I don’t extract strings and then ask the node operator to compare them. The source context is what makes the requested relationship meaningful.

WITH Source AS
(
 SELECT CAST(N'<Root><Item>zebra</Item><Item>apple</Item><Item>middle</Item></Root>' AS xml) AS Doc
)
SELECT Doc.value('(/Root/Item[1]/text())[1]','nvarchar(20)') AS FirstText,
       Doc.value('(/Root/Item[2]/text())[1]','nvarchar(20)') AS SecondText,
       Doc.value('if ((/Root/Item)[1] << (/Root/Item)[2]) then 1 else 0','int') AS FirstPrecedesSecond,
       Doc.value('if ((/Root/Item)[1] >> (/Root/Item)[2]) then 1 else 0','int') AS FirstFollowsSecond,
       Doc.value('if ((/Root/Item)[2] >> (/Root/Item)[1]) then 1 else 0','int') AS SecondFollowsFirst,
       Doc.value('if ((/Root/Item)[1] << (/Root/Item)[1]) then 1 else 0','int') AS FirstPrecedesSelf,
       Doc.value('if ((/Root/Item)[1] >> (/Root/Item)[1]) then 1 else 0','int') AS FirstFollowsSelf
FROM Source;
Native SSMS results show zebra preceding apple in XML document order, despite alphabetical order, with reverse-direction and self comparisons.
Native SSMS results show zebra preceding apple in XML document order, despite alphabetical order, with reverse-direction and self comparisons. Open the results at full size.

Read the precedes relationship

FirstPrecedesSecond expects one. The first Item occurs before the second Item in the document, regardless of their text. The << operator expresses that positional relationship.

I’d name the output Precedes rather than Smaller. Smaller can suggest a numeric or lexical comparison that this expression doesn’t perform. A report comparing process steps may care about their source sequence. That requirement should be stated explicitly instead of inferred from the visible values or a convenient alphabetical display.

Read the opposite direction

FirstFollowsSecond expects zero, while SecondFollowsFirst expects one. The >> operator reports whether its left node follows its right node. These two columns make the direction of the comparison visible.

I’d keep the operand order clear when adapting the expression. Swapping operands changes the question even though both nodes remain unchanged. A true result can otherwise be described backward in a caption. Complete aliases help a reviewer connect each decision to the actual paths used by the query.

Before, after and itself

Compare one node with itself

The final two columns compare the first Item with itself. Neither strict preceding nor strict following is true, so both expect zero. The node doesn’t occupy an earlier or later position than itself.

This is a useful boundary case beside the distinct-sibling comparisons. I’d retain it when writing an expected tuple for positional logic. A comparison intended to include identity needs another explicitly chosen rule. The strict order operators alone don’t express before-or-same or after-or-same.

Keep ordering concepts separate

Document order is a property of the source nodes. Sorting a derived report by text is another operation. That presentation choice shouldn’t silently change the relationship being described by these node comparisons.

I’d distinguish source position from any business sequence number stored in an attribute. The numbers might disagree with document order. The application must decide which convention governs its workflow. This example checks source order only, and makes no assumption about an external process definition.

Validate the selected nodes

The query reads inline XML and performs no writes. Its complete seven-column output shows the texts, both directions and the same-node controls. There is no separate dataset or hidden sorting step.

I’d inspect path cardinality before adapting the pattern to repeated nested groups. The fixed positions here always select one node. Optional elements or broader paths need their own handling. A positional comparison doesn’t establish that the selected nodes are the business records the consumer intended to compare.

Node order is source position, so preserve the node context and keep it separate from sorting the displayed values.

Node order is not sort order, it is where a node sits in the source document.

Published by Pinal Dave on SQLAuthority. More of my work at pinaldave.com.


Discover more from SQL Authority with Pinal Dave

Subscribe to get the latest posts sent to your email.

SQL Datatype, SQL Function, SQL Scripts
Previous Post
geometry STAsBinary: Carry the SRID Beside the WKB
Next Post
SQL SERVER – Selecting Domain from Email Address

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.