SQL - 通过条件对行进行分组,直到找到异常

时间:2013-09-09 18:31:05

标签: sql sql-server sql-server-2008

我正在尝试根据某些条件将数据列添加到数据集。举个简单的例子:

╔════╦══════╗
║ ID ║ DATA ║
╠════╬══════╣
║  1 ║   12 ║
║  2 ║   20 ║
║  3 ║    3 ║
║  4 ║   55 ║
║  5 ║   11 ║
╚════╩══════╝

假设我们的标准是数据应该大于10.那么结果应该类似于:

╔════╦══════╦═══════╗
║ ID ║ DATA ║ GROUP ║
╠════╬══════╬═══════╣
║  1 ║   12 ║     1 ║
║  2 ║   20 ║     1 ║
║  3 ║    3 ║     2 ║
║  4 ║   55 ║     3 ║
║  5 ║   11 ║     3 ║
╚════╩══════╩═══════╝

因此,在标准发生异常之前满足条件的所有行都成为组的一部分。该组的编号不一定需要遵循这种模式,我只是觉得这是一个逻辑/简单的编号来解释我正在寻找的解决方案。

2 个答案:

答案 0 :(得分:1)

您可以通过查找数据< = 10的每一行来计算组标识符。然后,组标识符就是在给定行之前该条件为真的行数。

select t.*,
       (select count(*)
        from t t2
        where t2.id <= t.id and
              t2.data <= 10
       ) as groupId
from t;

SQL Server 2012具有累积和语法。该声明在该数据库中会更简单:

select t.*,
       sum(case when t2.data <= 10) over (order by id) as groupId
from t;

编辑:

以上没有考虑到小于10的值在他们自己的组中。上面的逻辑是他们开始了一个新的团队。

以下分配了具有此约束的组ID:

select t.*,
       ((select 2*count(*)
         from t t2
         where t2.id < t.id and
               t2.data <= 10
        ) + (case when t.id <= 10 then 1 else 0 end)
       ) as groupId
from t;

答案 1 :(得分:1)

使用递归查询可以轻松完成此操作:

;WITH CTE 
     AS (SELECT *, 
                1 AS [GROUP] 
         FROM   TABLEB 
         WHERE  ID = 1 
         UNION ALL 
         SELECT T1.ID, 
                T1.DATA, 
                CASE 
                  WHEN T1.DATA < 10 THEN T2.[GROUP] + 1 
                  ELSE T2.[GROUP] 
                END [GROUP] 
         FROM   TABLEB T1 
                INNER JOIN CTE T2 
                        ON T1.ID = T2.ID + 1) 
SELECT * 
FROM   CTE 

可以在 SQL Fiddle 找到一个工作示例。

祝你好运!