Sql server中的FLWOR计数命中数

时间:2013-09-10 10:22:27

标签: sql-server-2008-r2 xquery xquery-sql flwor

我正在使用SQL Server 2008 R2。我的问题是我想要计算使用FLWOR从XQuery查询收到的点击次数。对于每次点击,我想要一个连续的数字,例如:0,1,2,3,4 ...

我的查询:

select @xml.query('for $s at $count in /Root/Persons/Person
return <Person ID="{$count}">{$s}</Person>')

此处唯一的问题是SQL Server不支持此操作,但收到错误:

Msg 9335, Level 16, State 1, Line 16
XQuery [query()]: The XQuery syntax 'at' is not supported.

我也尝试过let关键字并定义新变量,但我不知道如何在每次迭代时增加该变量的值?

感谢所有答案,Frenky

2 个答案:

答案 0 :(得分:5)

XQuery是一种声明性语言you cannot use let to increment a counter

缺少at功能的一个相当狡猾的解决方法是计算前面的兄弟<person/>标记:

for $person in /Root/Persons/Person
let $count := count($person/preceding-sibling::Person) + 1
return <Person ID="{$count}">{$person}</Person>

请注意,如果执行引擎(可能不会执行)优化,此代码将具有O(n^2)运行时,因为重复的先前兄弟扫描。


编辑:如评论中所述,MS SQL甚至不支持preceding-sibling轴。但他们确实支持<< node order comparison operator。应完全支持此查询:

for $person in /Root/Persons/Person
let $count := count($person/parent::Persons/Person[. << $person]) + 1
return <Person ID="{$count}">{$person}</Person>

顺便说一句,你可能只想粘贴这个人的名字,所以最好使用

(: snip :)
return <Person ID="{$count}">{data($person)}</Person>

答案 1 :(得分:0)

如果您对XQuery不熟悉,可能会更容易阅读的另一种可能的公式:

for $i in (1 to count(/Root/Persons/Person))
let $person := /Root/Persons/Person[$i]
return
    <Person ID="{$i}">{$person}</Person>

此外,如果SQL Server支持XQuery 3.0,那么您可以执行以下操作:

/Root/Persons/Person ! <Person ID="{position()}">{data(.)}</Person>