简体   繁体   中英

How to make a for loop work for xquery, in the context of 'contains'?

If we have a books.xml file like

<books>
    <book isbn="123">
        <collections>
            <collection c="1" />
            <collection c="2" />
            <collection c="3" />
            <collection c="4" />
        </collections>
    </book>
    <book isbn="234">
        <collections>
            <collection c="1" />
            <collection c="2" />
            <collection c="3" />
            <collection c="5" />
        </collections>
    </book>
</books>

I want to return all the ISBNs where both books belong to the same collections.

declare variable $doc := doc("books.xml");
<samecollections>
{ 
    for $b1 in $doc/books/book
    for $b2 in $doc/books/book
    where $b1 << $b2 and
        every $p in $b1/collections/collection 
        satisfies $p in $b2/collections/collection
    return 
    ...
}
</samecollections>

How would I make something like that work? I've tried inserting a for loop inside the where loop, but nothing worked, so I think I'm just really misunderstanding the syntax of xquery. Help?

Ideally, your XQuery processor supports group by , so the answer is fairly simple:

for $b in $books/book
let $colls-key := string-join($b/collections/collection/@c, '')
group by $colls-key
return element grouped {
    $b/@isbn/string()
}

If the collections aren't always ordered in the data, you can order them before generating your key:

let $colls-key := 
  string-join(
    for $c in $collections/collection/@c
    order by $c
    return $c)

Without group by it's a little messier.

declare function local:key($collections){
  string-join($collections/collection/@c, '')
};

for $key in distinct-values($doc/books/book/local:key(collections))
return element grouped {
  $doc/books/book[local:key(collections) eq $key]/@isbn/string()
}

Depending on the XQuery processor that also may be less efficient, so it's probably not advisable for large data sets. If performance is an issue, then you can look into what optimizations are available for your specific implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM