У меня есть следующие данные:Как сделать эффективное внешнее или левое соединение в XQuery?
<!-- subjects.xml -->
<Subjects>
<Subject>
<Id>1</Id>
<Name>Maths</Name>
</Subject>
<Subject>
<Id>2</Id>
<Name>Science</Name>
</Subject>
<Subject>
<Id>2</Id>
<Name>Advanced Science</Name>
</Subject>
<Subject>
<Id>3</Id>
<Name>History</Name>
</Subject>
</Subjects>
, который должен быть присоединен к:
<!-- courses.xml-->
<Courses>
<Course>
<SubjectId>1</SubjectId>
<Name>Algebra I</Name>
</Course>
<Course>
<SubjectId>1</SubjectId>
<Name>Algebra II</Name>
</Course>
<Course>
<SubjectId>1</SubjectId>
<Name>Percentages</Name>
</Course>
<Course>
<SubjectId>2</SubjectId>
<Name>Physics</Name>
</Course>
<Course>
<SubjectId>2</SubjectId>
<Name>Biology</Name>
</Course>
</Courses>
Я хотел бы сделать левый присоединиться к первой таблицы для второй таблицы таким образом, чтобы получить следующее выход:
<Results>
<Result>
<Table1>
<Subject>
<Id>1</Id>
<Name>Maths</Name>
</Subject>
</Table1>
<Table2>
<Course>
<SubjectId>1</SubjectId>
<Name>Algebra I</Name>
</Course>
<Course>
<SubjectId>1</SubjectId>
<Name>Algebra II</Name>
</Course>
<Course>
<SubjectId>1</SubjectId>
<Name>Percentages</Name>
</Course>
</Table2>
</Result>
<Result>
<Table1>
<!-- Notice there are 2 subjects here, as they both have the same ID-->
<Subject>
<Id>2</Id>
<Name>Science</Name>
</Subject>
<Subject>
<Id>2</Id>
<Name>Advanced Science</Name>
</Subject>
</Table1>
<Table2>
<Course>
<SubjectId>2</SubjectId>
<Name>Physics</Name>
</Course>
<Course>
<SubjectId>2</SubjectId>
<Name>Biology</Name>
</Course>
</Table2>
</Result>
<Result>
<Table1>
<Subject>
<Id>3</Id>
<Name>History</Name>
</Subject>
</Table1>
<Table2>
<!-- Notice this section is empty -->
</Table2>
</Result>
</Results>
у меня есть следующий код, чтобы сделать это:
<Results>
{
(: For each element in courses, where it's 'SubjectId' exists in "subjects.xml":)
for $e2 in doc("courses.xml")/Courses/Course
let $foriegnId := $e2/SubjectId
group by $foriegnId
let $e1 := doc("subjects.xml")/Subjects/Subject[Id = $foriegnId]
where $e1
return
<Result>
<Table1>
{$e1}
</Table1>
<Table2>
{$e2}
</Table2>
</Result>
}
{
(: PART2 :)
(:Show the remaining elements in courses that have not yet been outputted:)
for $e1 in doc('subjects.xml')/Subjects/Subject
let $idVal := $e1/Id
group by $idVal
where not(doc('courses.xml')/Courses/Course/SubjectId = $idVal)
return
<Result>
<Table1>
{$e1}
</Table1>
<Table2/>
</Result>
}
</Results>
Обратите внимание, что код работает нормально и выполняет эту работу. Тем не менее, я обнаружил, что при выполнении кода для больших входов (750 предметов, каждый из которых содержит 120 курсов, а также 100 предметов без курсов и 100 курсов без каких-либо предметов), скрипт работает очень медленно!
Что я могу сделать, чтобы сделать мой скрипт быстрее? Есть ли лучший способ сделать это? Какова временная сложность?
Update 2
Оказывается, я сильно не распознали проблему. Проблема на самом деле была очень мало связана с частью 2 кода, а скорее с частью 1 кода.
Что я сделал:
for $e2 in doc("courses.xml")/Courses/Course
let $foriegnId := $e2/SubjectId
let $e1 := doc("subjects.xml")/Subjects/Subject[Id = $foriegnId]
group by $foriegnId
когда то, что я должен был сделать было:
for $e2 in doc("courses.xml")/Courses/Course
let $foriegnId := $e2/SubjectId
group by $foriegnId
let $e1 := doc("subjects.xml")/Subjects/Subject[Id = $foriegnId]
Это уменьшило время кода от 30,000ms около 4,000ms.
Дальнейшие улучшения производительности приветствуются.
Можете ли вы дать ваши измерения? Вы используете Saxon-HE или Saxon-EE? –
Для проблем с бенчмаркингом с большими наборами данных вряд ли полезно предоставлять только небольшие выдержки (отлично подходит для самого вопроса, но вы должны предоставить набор данных, который вы сравниваете с самим собой). Также полезно дать точную версию программного обеспечения. –
Saxon 9.7 - это evrsion. Я использую –