count distinct multiple values in XQuery

65 views Asked by At

Given the XML Document below.this XML document contains many books. books can be authored by many authors: *

`<bib>
 <book year="1994">
 <title>TCP/IP Illustrated</title>
 <author>
 <last>Stevens</last>
 <first>W.</first>
 </author>
 <publisher>Addison-Wesley</publisher>
 <price>65.95</price>
 </book>
 <book year="1992">
 <title>Advanced Programming in the UNIX Environment</title>
 <author>
  <last>Stevens</last>
  <first>W.</first>
  </author>
  <publisher>Addison-Wesley</publisher>
  <price>39.95</price>
  </book>
  <book year="2000">
  <title>Data on the Web</title>
  <author>
  <last>Abiteboul</last>
  <first>Serge</first>
  </author>
  <author>
  <last>Buneman</last>
  <first>Peter</first>
  </author>
  <author>
  <last>Suciu</last>
  <first>Dan</first>
  </author>
  <publisher>Morgan Kaufmann Publishers</publisher>
  <price>39.95</price>
  </book>
  <book year="1999">
  <title>The Economics of Technology and Content for Digital TV</title>
  <publisher>Kluwer Academic Publishers</publisher>
  <price>129.95</price>
  </book>
</bib>`

I want to output , from this document, the number of authors without duplicates.

I have tried the following:

let $x:= distinct-values(doc('biblio.xml')//author/(first, last))
return count ($x)

but this query , Unfortunately, doesn't give me the expected output.

3

There are 3 answers

1
Martin Honnen On BEST ANSWER

You can group the author elements by the first and last element and then count the groups:

(for $author in //author
group by $first := $author/first, $last := $author/last
return $author[1]) => count()
0
Yitzhak Khabinsky On

Please try the following solution. Tested in BaseX 11.0 beta.

XQuery

declare context item := document {
<bib>
    <book year="1994">
        <title>TCP/IP Illustrated</title>
        <author>
            <last>Stevens</last>
            <first>W.</first>
        </author>
        <publisher>Addison-Wesley</publisher>
        <price>65.95</price>
    </book>
    <book year="1992">
        <title>Advanced Programming in the UNIX Environment</title>
        <author>
            <last>Stevens</last>
            <first>W.</first>
        </author>
        <publisher>Addison-Wesley</publisher>
        <price>39.95</price>
    </book>
    <book year="2000">
        <title>Data on the Web</title>
        <author>
            <last>Abiteboul</last>
            <first>Serge</first>
        </author>
        <author>
            <last>Buneman</last>
            <first>Peter</first>
        </author>
        <author>
            <last>Suciu</last>
            <first>Dan</first>
        </author>
        <publisher>Morgan Kaufmann Publishers</publisher>
        <price>39.95</price>
    </book>
    <book year="1999">
        <title>The Economics of Technology and Content for Digital TV</title>
        <publisher>Kluwer Academic Publishers</publisher>
        <price>129.95</price>
    </book>
</bib>
};

(: let $x:= distinct-values(doc('d:\temp\biblio.xml')/bib/book/author/(first || last)) :)
let $x:= distinct-values(./bib/book/author/(first || last))
return count($x)

Output

4
1
Jack Fleeting On

Try changing your xpath expression to

distinct-values(//author/concat(last, first))

should output 4 based on your sample