我们假设这个表格包含RowID
和Call
列:
RowID Call DesiredOut
1 A 0
2 A 0
3 B
4 A 1
5 A 0
6 A 0
7 B
8 B
9 A 2
10 A 0
我想SQL查询最后一列DesiredOut
,如下所示:
每次Call
是' A'回去直到' A'再次找到并计算两个' A'之间的记录数量。条目。
示例:RowID
4有' A'最近的前任位于RowID
2.在RowID
2和RowID
之间我们有一个Call
' B',所以我们算上1. / p>
使用ANSI SQL是否有一种优雅且高效的方法?
答案 0 :(得分:2)
我会先找到前一个“A”值的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
是连续的,没有间隙,则可以在外部查询中使用减法而不是子查询进行计算。
答案 1 :(得分:1)
您可以使用查询来查找之前的Call = A
行。然后,您可以计算该行与当前行之间的行数:
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
答案 2 :(得分:1)
以下是使用窗口函数的另一种解决方案:
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示例:http://sqlfiddle.com/#!15/e1840/1
答案 3 :(得分:1)
信不信由你,如果将两列编入索引,这将非常快。
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';
这是 Fiddle 。
答案 4 :(得分:0)
你可以这样做:
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,所以更多种类的伪代码可以根据你的系统运行。