SQL:获取正在运行的记录行增量

SQL:获取正在运行的记录行增量,sql,Sql,假设我们有一个列为RowID和Call的表: 我想用SQL查询所需的最后一列,如下所示: 每次调用都是“A”,请返回,直到再次找到“A”,并计算两个“A”条目之间的记录数 示例:rowid4有“A”,最近的前置项在rowid2中。在rowid2和rowid4之间,我们有一个调用“B”,所以我们计算1 使用ANSI SQL是否有一种优雅而高效的方法可以做到这一点?您可以这样做: SELECT a.rowid - b.rowid FROM table as a, (SELECT row

假设我们有一个列为RowID和Call的表:

我想用SQL查询所需的最后一列,如下所示: 每次调用都是“A”,请返回,直到再次找到“A”,并计算两个“A”条目之间的记录数

示例:rowid4有“A”,最近的前置项在rowid2中。在rowid2和rowid4之间,我们有一个调用“B”,所以我们计算1


使用ANSI SQL是否有一种优雅而高效的方法可以做到这一点?

您可以这样做:

SELECT a.rowid - b.rowid 
FROM table as a, 
     (SELECT rowid FROM table where rowid < a.rowid order by rowid) as b
WHERE <something>
ORDER BY a.rowid

因为我不能说您使用的是哪种DBMS,所以这是一种伪代码,可以基于您的系统工作

您可以使用查询来查找前一个调用=一行。然后,您可以计算该行和当前行之间的行数:

select  RowID
,       `Call`
,       (
        select  count(*)
        from    YourTable t2
        where   RowID < t1.RowID
                and RowID > coalesce(
                    (
                    select  RowID
                    from    YourTable t3
                    where   `Call` = 'A'
                            and RowID < t1.RowID
                    order by
                            RowID DESC
                    limit 1
                    ),0)
        )
from    YourTable t1

我将通过首先查找前一个值的rowid来实现这一点。然后计算两者之间的数值

以下查询使用相关子查询实现此逻辑:

select t.*,
       (case when t.call = 'A'
             then (select count(*)
                   from table t3
                   where t3.id < t.id and t3.id > prevA
                  )
        end) as InBetweenCount
from (select t.*,
             (select max(rowid)
              from table t2
              where t2.call = 'A' and t2.rowid < t.rowid
             ) as prevA
      from table t
     ) t;

如果您知道rowid是连续的,没有间隔,您可以在外部查询中使用减法而不是子查询进行计算。

下面是使用窗口函数的另一种解决方案:

with flagged as (
  select *,
         case
            when call = 'A' and lead(call) over (order by rowid) <> 'A' then 'end'
            when call = 'A' and lag(call) over (order by rowid) <> 'A' then 'start'
          end as change_flag
  from calls
)
select t1.rowid,
       t1.call,
       case 
         when change_flag = 'start' then rowid - (select max(t2.rowid) from flagged t2 where t2.change_flag = 'end' and t2.rowid < t1.rowid) - 1
         when call = 'A' then 0
       end as desiredout
from flagged t1
order by rowid;
CTE首先标记每个A块的开始和结束,然后最终选择使用这些标记获取一个块的开始和上一个块的结束之间的差异

如果rowid不是无间隙,则可以在CTE内轻松添加无间隙rownumber以计算差值

不过,我对表演不太确定。如果戈登的回答更快,我也不会感到惊讶


SQLFiddle示例:

信不信由你,如果这两列都被索引了,这将非常快

select  r1.RowID, r1.CallID, isnull( R1.RowID - R2.RowID - 1, 0 ) as DesiredOut
from    RollCall R1
left join RollCall R2
    on  R2.RowID =(
        select  max( RowID )
        from    RollCall
        where   RowID < R1.RowID
            and CallID = 'A')
    and R1.CallID = 'A';

以下是。

rowid是否自动生成并存储在数据库中?您使用的是什么数据库?rowid没有间隙。我将尝试所有答案并比较运行时,因为所讨论的表是巨大的。@Juergen:严格地说,这个答案不是ANSI SQL btw。
select  r1.RowID, r1.CallID, isnull( R1.RowID - R2.RowID - 1, 0 ) as DesiredOut
from    RollCall R1
left join RollCall R2
    on  R2.RowID =(
        select  max( RowID )
        from    RollCall
        where   RowID < R1.RowID
            and CallID = 'A')
    and R1.CallID = 'A';