0

我有以下数据:

<!-- 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 个没有任何科目的课程),脚本运行速度极慢!

我可以做些什么来让我的脚本更快?有没有更好的方法来做到这一点?时间复杂度是多少?

更新 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,000 毫秒减少到了 4,000 毫秒左右。

欢迎进一步的性能改进。

4

1 回答 1

1

根据查询的优化方式,ID 列表可能会一次又一次地放在一起,每个主题一次。提前获取列表一次,然后对此进行验证。

    let $subjectIds := doc('courses.xml')/Courses/Course/SubjectId
    for $e1 in doc('subjects.xml')/Subjects/Subject
    let $idVal := $e1/Id
    group by $idVal
    where not($subjectIds = $idVal)
    return
        <Result>
            <Table1>
                {$e1}
            </Table1>
            <Table2/>
        </Result>

进一步的优化可能是将部分冗余的主题 ID 列表修剪为它们之前的不同值序列:

    let $subjectIds := distinct-values(doc('courses.xml')/Courses/Course/SubjectId)
于 2015-12-03T14:18:39.073 回答