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.