【问题标题】:Xquery Get Consecutive Distinct ValuesXquery 获取连续的不同值
【发布时间】:2022-01-12 02:26:52
【问题描述】:

尝试从以下 XML 中获取连续的不同。

<x>
    AB
</x>
<x>
    AB
</x>
<x>
    AB
</x>
<x>
    AC
</x>
<x>
    AB
</x>

预期结果:

AB AC AB

当前结果:

AB AC

代码:

SELECT * ,STUFF(( TheParts.query(' for $x in distinct-values(/x/text()) return <x>{concat(" | ", $x)}</x> ').value('.', 'varchar(max)') ), 1, 1, '') AS Hierarchy 
FROM Table

distinct-values 与整个集合不同,但我想只有在有连续的情况下才能获得不同的值。

【问题讨论】:

    标签: sql sql-server xml xquery xquery-sql


    【解决方案1】:

    我们有一个纯 XQuery 解决方案。

    SQL

    SELECT REPLACE(CAST('<x>AB</x>
        <x>AB</x>
        <x>AB</x>
        <x>AC</x>
        <x>AB</x>' as xml)
    .query('
        for $v in x
        let $n := x[. >> $v][1]
        return if ($v/text()[1] = $n/text()[1]) then ()
                else data($v)
    ').value('.', 'VARCHAR(MAX)'), SPACE(1), ' | ') AS Result;
    

    输出

    +--------------+
    |    Result    |
    +--------------+
    | AB | AC | AB |
    +--------------+
    

    【讨论】:

    • 干得好! FLWOR 让我的大脑流血了。
    • 这太棒了。是否有可能将这些值作为管道分隔?就像我在查询中尝试的方式一样。
    • 我调整了答案。看看吧。
    • 观察:根据我的测试,该解决方案的执行速度似乎比 your SQL solution 快 2 倍以上
    【解决方案2】:

    fiddle

    select
    cast('<x>AB</x>
    <x>AB</x>
    <x>AB</x>
    <x>AC</x>
    <x>AB</x>' as xml).query('
    for $v in x
    let $n := x[. >> $v][1]
    where not($v/text() = $n/text())
    return (string($v/text()[1]))
    ')
    

    fiddle

    select stuff(
    cast('<x>AB</x>
    <x>AB</x>
    <x>AB</x>
    <x>AC</x>
    <x>AB</x>' as xml).query('
    for $v in x/text()
    let $n := x[. >> $v][1]/text()
    where not($v = $n)
    return text{concat(" | ", $v)}
    ').value('.', 'nvarchar(max)'), 1, 3, '')
    
    
    select stuff(
    cast('<x>AB</x>
    <x>AB</x>
    <x>AB</x>
    <x></x>
    <x></x>
    <x></x>
    <x></x>
    <x></x>
    <x></x>
    <x>AC</x>
    <x>AB</x>' as xml).query('
    for $v in x
    let $n := x[. >> $v][1]
    where not($v/text()= $n/text() or (empty($v/text()) and empty($n/text())))
    return text{concat(" | ", $v/text()[1])}
    ').value('.', 'nvarchar(max)'), 1, 3, '')
    

    一种更快的方法,与 xquery 中的想法相同:查找序列的最后一个值。 fiddle

    select s.hierarchy
    from t 
    cross apply
    (
    select string_agg(isnull(x, ''), ' | ') within group(order by rn) as hierarchy
    from
    (
        select rn, x, lead(x) over(order by rn) as n
        from
        (
        select row_number() over(order by n.x) as rn, n.x.value('text()[1]', 'varchar(20)') as x
        from t.TheParts.nodes('x') as n(x)
        ) as d
    ) as l
    where isnull(x, char(1)) <> isnull(n, char(1))
    ) as s
    

    【讨论】:

      【解决方案3】:

      请尝试以下解决方案。它不是基于 XQuery 的。

      不幸的是,MS SQL Server 的 XQuery 只支持 XQuery 1.0 标准的一个子集。

      翻转窗口和窗口变量功能是 XQuery 3.0/3.1 标准的一部分。

      在这里查看:window clause

      请为我的建议投票:SQL Server vNext (post 2019) and NoSQL functionality

      SQL

      DECLARE @xml XML = 
      N'<root>
          <x>AB</x>
          <x>AB</x>
          <x>AC</x>
          <x>AC</x>
          <x>AB</x>
      </root>';
      
      WITH rs AS
      (
          SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS seq
              , c.value('text()[1]','CHAR(2)') AS R
          FROM @xml.nodes('/root/x') AS t(c)
      ), cte AS
      (
       SELECT *, SUM(IIF(R <> ns, 1, 0)) OVER (ORDER BY seq) AS series
          FROM (
              SELECT series.*,
                     LAG(R) OVER (ORDER BY seq) AS ns
              FROM rs AS series
          ) q
      )
      --SELECT * FROM cte ORDER BY seq;
      SELECT MIN(R) AS R, series, MIN(cte.seq) AS seq_min, MAX(cte.seq) AS seq_max
      FROM cte
      GROUP BY cte.series
      ORDER BY MAX(cte.seq) ASC;
      

      输出

      +----+--------+---------+---------+
      | R  | series | seq_min | seq_max |
      +----+--------+---------+---------+
      | AB |      0 |       1 |       2 |
      | AC |      1 |       3 |       4 |
      | AB |      2 |       5 |       5 |
      +----+--------+---------+---------+
      

      【讨论】:

      • 我调整了答案。看看吧。
      • 观察:根据我的测试,您的 XQuery 解决方案的执行速度似乎快了 2 倍以上。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-31
      • 2012-09-23
      • 2019-07-28
      • 1970-01-01
      • 2013-11-13
      • 2013-12-27
      • 2015-06-17
      相关资源
      最近更新 更多