Il peut être un peu plus court avec une série de 3 CROSS APPLY, niveau par niveau
SELECT HistoryId,
t.qID,
t.questionText,
t.result,
a.aId,
a.answerNbr,
a.answerChosen,
a.answerTxt
FROM
tbl_QuizHistory
CROSS APPLY QuizData.nodes('quizresult') AS n(q)
CROSS APPLY (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS qID,
t.q.value('(./questionText)[1]', 'nvarchar(max)') AS questionText,
t.q.value('(./result)[1]', 'nvarchar(50)') AS result,
t.q.query('.') queryXml
FROM
n.q.nodes('./question') t(q)
) t
CROSS APPLY (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS aID,
q.a.value('(./@number)[1]', 'int') as answerNbr,
q.a.value('(./@chosen)[1]', 'bit') as answerChosen,
q.a.value('.','nvarchar(max)') as answerTxt
FROM
t.queryXml.nodes('question/answer') q(a)
) a;
S'il n'y a pas de calculs spécifiques au niveau (par exemple, row_number()
) sont nécessaires :
SELECT HistoryId,
t.qID,
t.questionText,
t.result,
q.a.value('(./@number)[1]', 'int') as answerNbr,
q.a.value('(./@chosen)[1]', 'bit') as answerChosen,
q.a.value('.','nvarchar(max)') as answerTxt
FROM
tbl_QuizHistory
CROSS APPLY QuizData.nodes('quizresult') AS n(q)
CROSS APPLY (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS qID,
t.q.value('(./questionText)[1]', 'nvarchar(max)') AS questionText,
t.q.value('(./result)[1]', 'nvarchar(50)') AS result,
t.q.query('.') queryXml
FROM n.q.nodes('./question') t(q)
) t
CROSS APPLY t.queryXml.nodes('question/answer') q(a)