The let clause assigns a variable to the entire result of an expression. Here is an example:
let $i := (1,2,3) return <tuple>{$i}</tuple>
The result is a unique tuple element containing the entire sequence assigned in the let clause:
<tuple>1 2 3</tuple>
Here is an example on XMark documents:
let $p := doc("auction.xml")/site/people/person return <names>{$p/name}</names>
The result is something like this:
<names> <name>Huei Demke</name> <name>Daishiro Juric</name> <name>Kawon Unni</name> <name>Ewing Andrade</name> </names>
In order to understand the semantic difference between for and let clauses, it is instructive to compare the above query with the following one:
for $p in doc("auction.xml")/site/people/person return <names>{$p/name}</names>
whose result is something like the following:
<names> <name>Huei Demke</name> </names> <names> <name>Daishiro Juric</name> </names> <names> <name>Kawon Unni</name> </names> <names> <name>Ewing Andrade</name> </names>
To conclude, here is a more involving example using both for and let clauses. The query returns all open auctions with the corresponding number of bidders. The variable a is assigned to all open auctions by the for clause. For each open auction, the let clause assigns the variable b to all bidders of the current open auction. Finally, for each open auction, the return clause outputs the auction id attribute as long as the number of auction bidders:
for $a in doc("auction.xml")/site/open_auctions/open_auction let $b := $a/bidder return <auction id = "{$a/@id}"> <bidder_count>{count($b)}</bidder_count> </auction>