从下一行开始,根据当前值对行进行分组

时间:2019-01-25 09:39:24

标签: sql sql-server

我需要使用value <> z为所有下一行增加组号。 z表示根据b的所有下一行将具有相同的组号。

CREATE TABLE #tmp
(
    a CHAR(1)
  , b INT
);

INSERT INTO #tmp (a
                , b)
VALUES ('a', 1)
     , ('b', 2)
     , ('z', 3)
     , ('c', 4)
     , ('z', 5)
     , ('z', 6)
     , ('d', 7);

SELECT       t.a
           , t.b
           , SUM(v.is_z) OVER (ORDER BY t.b ROWS UNBOUNDED PRECEDING) - ROW_NUMBER() OVER (ORDER BY t.b) group_nbr
  FROM       #tmp                                                 AS t
 CROSS APPLY (SELECT CASE WHEN a = 'z' THEN 2 ELSE 1 END AS is_z) AS v
 ORDER BY 2;

DROP TABLE #tmp;

在我的查询中,该组从值z的行开始递增,但是我需要为下一行开始递增。

预期输出:

enter image description here

3 个答案:

答案 0 :(得分:4)

一种解决方案是,每次找到z时将结果加1,然后将LAG的结果最后加1行。

;WITH CumulativeZ AS
(
    SELECT
        T.*,
        CumulativeZ = SUM(CASE WHEN T.a = 'z' THEN 1 ELSE 0 END) OVER(ORDER BY T.b ASC)
    FROM
        #tmp AS T
)
SELECT
    C.a,
    C.b,
    C.CumulativeZ,
    [Group] = LAG(C.CumulativeZ, 1, 0) OVER (ORDER BY C.b ASC)
FROM
    CumulativeZ AS C

结果:

a   b   CumulativeZ Group
a   1   0           0
b   2   0           0
z   3   1           0
c   4   1           1
z   5   2           1
z   6   3           2
d   7   3           3

请注意,LAG函数适用于SQL Server 2012+。您可以在版本2008+上使用ROW_NUMBER来模仿它的功能。

答案 1 :(得分:1)

我只会使用apply

select t.a, t.b, tt.grp
from #tmp t outer apply
     (select count(*) as grp
      from #tmp t1 
      where t1.b < t.b and t1.a = 'z'
     ) tt;

答案 2 :(得分:1)

您希望“ z”标识组的结尾。您可以使用累计和分配组号。我认为这是您要做的最简单的方法。

如果您不关心数字的实际顺序,则只需执行以下操作即可:

select t.*,
       sum(case when a = 'z' then 1 else 0 end) over (order by b desc) as grp_desc 
from #tmp t;

如果要将组编号为“正确的方式”,则可以使用稍微复杂一点的表达式:

select t.*,
       coalesce(sum(case when a = 'z' then 1 else 0 end) over
                    (order by b
                     rows between unbounded preceding and 1 preceding), 0
               ) as grp
from #tmp t;

Here是db <>小提琴。