I make XPath first items explicit because the placement of [1] changes which sequence it filters. One expression selects the first Item under each Group. Parentheses can instead select one first Item from the complete path result.

Use more than one parent
The first document has two populated Group elements and one empty Group. Each populated group contains two Items. A single populated group wouldn’t expose the difference between the two path expressions.
I keep the Item values distinct so each selection can be identified. A1 and A2 belong to the first group. B1 and B2 belong to the second. The empty third group has no first Item to contribute. These fixed inputs make every selected node traceable.
WITH Inputs AS
(
SELECT CaseId, CAST(XmlText AS xml) AS Doc
FROM (VALUES
(1,N'<Root><Group><Item>A1</Item><Item>A2</Item></Group><Group><Item>B1</Item><Item>B2</Item></Group><Group/></Root>'),
(2,N'<Root><Group/><Group/></Root>')
) v(CaseId,XmlText)
)
SELECT CaseId,
CAST(Doc.query('/Root/Group/Item[1]') AS nvarchar(max)) AS FirstPerGroup,
CAST(Doc.query('(/Root/Group/Item)[1]') AS nvarchar(max)) AS FirstOverall,
Doc.value('count(/Root/Group/Item[1])','int') AS PerGroupCount,
Doc.value('count((/Root/Group/Item)[1])','int') AS OverallCount
FROM Inputs
ORDER BY CaseId;

Read the step-local predicate
The path /Root/Group/Item[1] attaches the positional predicate to the Item step. It selects the first Item child for each selected Group. Its expected fragment contains A1 followed by B1.
PerGroupCount expects two, not one. A [1] in a path doesn’t automatically promise a single result for the entire document. I’d review the parent sequence before making that claim. The number of selected parents can determine how many first children survive this step-local filter.
Read the parenthesized path
The expression (/Root/Group/Item)[1] first forms the complete path result, then selects its first node. For this document, its expected fragment contains only A1. OverallCount therefore expects one.
The difference comes from where the predicate is applied, not from another source document. I’d keep the parentheses visible in a copyable query. Removing them while simplifying code can change the selection contract. A shorter-looking path can still return valid XML while selecting additional nodes the caller didn’t expect.

Keep the full XML fragment
Both output fragments retain Item elements, not just concatenated display text. The first column can contain multiple sibling elements. SQL Server’s XML value can represent that fragment without an invented wrapper element.
I’d compare the full selected XML and the counts together. A count alone doesn’t establish that the right Items were chosen. A single text extraction could also hide additional nodes. These small fragments show both selection scope and the particular source children that meet it.
Read an empty selection honestly
The second document contains only empty Group elements. Both paths return empty XML fragments, displayed here as empty strings. Their expected counts are zero. This differs from SQL NULL, which the example doesn’t supply.
I’d avoid replacing an empty selection with a fabricated first Item. The source simply contains no eligible child. A consumer requiring at least one item must enforce that requirement separately. The positional predicate doesn’t create a node when there is nothing available to select.
Choose the intended scope first
The query reads two inline documents and makes no writes. CaseId orders their output. Every result column belongs to the expected comparison, including the empty fragments and zero counts.
I’d decide whether the application needs one item per group or one item overall before editing the path. The correct syntax follows that requirement. Neither form is a universal fix for repeated data. Verify the source nesting and intended selection boundary before relying on a first-item shortcut.
Where the brackets sit decides what comes back.
The [1] is not a global first, it is a filter on the step it follows.
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.




