【问题标题】:Select child nodes until attribute value in xpath (SQL Server)选择子节点直到 xpath 中的属性值(SQL Server)
【发布时间】:2013-12-17 02:46:47
【问题描述】:

我在 SQL Server 数据库 (SQL Server 2012) 中有一个 XML 列,其结构如下:

<history>
    <status updatedAt="2013-11-30" active="true" />
    <status updatedAt="2013-11-15" active="false" />
    <status updatedAt="2012-05-10" active="true" />
    <status updatedAt="2012-01-30" active="true" />
</history>

较新的状态作为顶部节点添加到列中。

我需要选择&lt;status&gt; 节点的子集,其中包括updatedAt 属性小于或等于给定日期的第一个节点以及所有前面的节点(或者,所有&lt;status> 节点直到updatedAt 属性为小于或等于给定日期)。

如何使用 XPath 实现这一点?

DECLARE @date DATE = '2012-30-10';
SELECT Statuses = Statuses.query('what should be there?')

现在我结束了这个查询:

SELECT Statuses = Statuses.query'((/history/pricing[@updatedAt <= sql:variable("@date")])[1])')

但它只返回第一个节点,我怎样才能包含它之前的所有兄弟节点?

【问题讨论】:

  • 由于您有美式日期,因此将日期作为字符串进行比较就足够了。但是,字符串比较 () 在 XPath 1.0 中不可用,这需要您将字符串日期分解为其组件。因此,问题是:您是否允许使用 XPath 2.0?
  • 参见解决方案 #3 和 #4。
  • 我的 XML 列是强类型的,根据架构,updatedAt 属性的类型是 xs:date。 SQL Server 将它与 DATE 类型的 SQL 变量进行正确比较。请看我的更新。根据 MSDN,Sql Server 支持 XPath 2.0。
  • SQL Server 实现了 XQuery 1.0 的大部分,其中包括 XPath 2.0。
  • @nativehr:如果您从最后一个 XQuery 中删除 [1],那么您应该收到所有节点,而不仅仅是第一个节点。

标签: sql-server xpath xml-column


【解决方案1】:

要获取所有前面的兄弟姐妹,请使用preceding-siblings 轴并选择最后一个之前匹配&lt;pricing/&gt;标签的所有兄弟姐妹。

SELECT Statuses = Statuses.query('
  /history/pricing[
      @updatedAt <= sql:variable("@date") and last()
  ]/preceding-sibling::pricing')

顺便说一句,虽然您的示例数据有 &lt;status/&gt; 标签,但您的查询需要 &lt;pricing/&gt; 标签?


我忘记了 MS SQL Server 不支持该轴,但它支持节点顺序运算符 &lt;&lt;,您可以使用它来解决这个问题。此查询表示“选择出现在具有此值的最后一个定价节点之前的所有定价节点”。

/history/pricing[. << (/history/pricing[@updatedAt <= "2012-30-10"])[last()]]

试试SQL Fiddle

【讨论】:

  • SQL Server 不支持preceding-sibling 轴。无论如何,谢谢你的回答!
  • 我的错,不是我第一次陷入这种困境。我希望我能够在未来的某个时候记住这一点...但这不是一个真正的问题,添加了一个解决方法,包括用于测试的 SQL fiddle。
  • Jens,这只是一个错字,当然应该有status 标签而不是pricing。你的最后一个例子就是我要找的,再次感谢你!
  • 不客气。 SQL Server 缺少一些 XQuery 功能是可怕的,我还没有找到它们的完整列表。另一个缺失的功能是您不能在元素构造函数的名称字段中使用变量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
  • 2013-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-15
  • 1970-01-01
相关资源
最近更新 更多