I have an XML document snippet that matches this XSD:
<xs:complexType name="QuestionType">
<xs:sequence>
<xs:element name="questionId" type="xs:string" minOccurs="1" />
<xs:element name="questionDescription" type="xs:string" minOccurs="1" />
<xs:element name="questionHeader" type="xs:string" minOccurs="0" />
<xs:element name="questionLabel" type="xs:string" minOccurs="0" />
<xs:element name="version" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="SubQuestion" type="QuestionType"
minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
This recursively defines a <Question> elements that can have an infite number of <SubQuestion> elements, both of the type QuestionType.
Using SQL, I’d like to query the document once to get a single result set with all of the questions and sub-questions. I have two independent queries at the moment to achieve this (please note that I’m using NVarChar(1000) for testing purposes only – they will be more appropriately sized in production, and that @X is an XML variable that matches the schema above):
SELECT -- Top-level questions...
C.value('questionId[1]', 'NVarChar(1000)') Id,
NULL ParentId,
C.value('questionDescription[1]', 'NVarChar(1000)') Description,
NULLIF(C.value('questionHeader[1]', 'NVarChar(1000)'), '') Header,
NULLIF(C.value('questionLabel[1]', 'NVarChar(1000)'), '') Label,
C.value('version[1]', 'NVarChar(1000)') Version
FROM @X.nodes('//Question') X(C);
SELECT -- Sub-questions...
C.value('questionId[1]', 'NVarChar(1000)') Id,
C.query('..').value('(Question/questionId)[1]', 'NVarChar(1000)') ParentId,
C.value('questionDescription[1]', 'NVarChar(1000)') Description,
NULLIF(C.value('questionHeader[1]', 'NVarChar(1000)'), '') Header,
NULLIF(C.value('questionLabel[1]', 'NVarChar(1000)'), '') Label,
C.value('version[1]', 'NVarChar(1000)') Version
FROM @X.nodes('//SubQuestion') X(C);
I’d expect this could be solved using a recursive CTE, but I’m having trouble putting one together.
Given that you have tagged this question with sql-server-2008 and that IMHO SQL Server 2008 has support for XQuery I would like to suggest a different “angle”: use an XPath expression to select the nodes you are interested in.
Please note that I am using the XPath function local-name() in case your real XML data has namespace declarations.
I have created a sample XML file to test the expression above:
Evaluating this XQuery query against that sample
will result in
EDIT – Final Query