Sql 在同一列中的1之间计算0
我有这样的数据Sql 在同一列中的1之间计算0,sql,oracle,Sql,Oracle,我有这样的数据 ID IND 1 0 2 0 3 1 4 0 5 1 6 0 7 0 我想在值1之前数零。因此,输出如下所示 ID IND OUT 1 0 0 2 0 0 3 1 2 4 0 0 5 1 1 6 0 0 7 0 2 没有pl/sql是否可能?我试图找出行号之间的差异,但未能实现。您可以将其视为一个间隙和孤岛问题。您可以通过“1”的个数或每行后面的个数来定义“孤岛”。然后使用
ID IND
1 0
2 0
3 1
4 0
5 1
6 0
7 0
我想在值1之前数零。因此,输出如下所示
ID IND OUT
1 0 0
2 0 0
3 1 2
4 0 0
5 1 1
6 0 0
7 0 2
没有pl/sql是否可能?我试图找出行号之间的差异,但未能实现。您可以将其视为一个间隙和孤岛问题。您可以通过“1”的个数或每行后面的个数来定义“孤岛”。然后使用窗口功能:
select t.*,
(case when ind = 1 or row_number() over (order by id desc) = 1
then sum(1 - ind) over (partition by grp)
else 0
end) as num_zeros
from (select t.*,
sum(ind) over (order by id desc) as grp
from t
) t;
如果id
是连续的,没有间隙,则无需子查询即可执行此操作:
select t.*,
(case when ind = 1 or row_number() over (order by id desc) = 1
then id - coalesce(lag(case when ind = 1 then id end ignore nulls) over (order by id), min(id) over () - 1)
else 0
end)
from t;
我建议删除
case
条件,只对表达式使用then
子句,这样所有行上都有值。您可以将此视为间隙和孤岛问题。您可以通过“1”的个数或每行后面的个数来定义“孤岛”。然后使用窗口功能:
select t.*,
(case when ind = 1 or row_number() over (order by id desc) = 1
then sum(1 - ind) over (partition by grp)
else 0
end) as num_zeros
from (select t.*,
sum(ind) over (order by id desc) as grp
from t
) t;
如果id
是连续的,没有间隙,则无需子查询即可执行此操作:
select t.*,
(case when ind = 1 or row_number() over (order by id desc) = 1
then id - coalesce(lag(case when ind = 1 then id end ignore nulls) over (order by id), min(id) over () - 1)
else 0
end)
from t;
我建议删除
case
条件,只对表达式使用then
子句,因此值在所有行上。Oracle 12.1中引入的match\u recognize
子句可以快速解决此类“行模式识别”问题。由于对ID=0的“最后一行”进行了特殊处理,解决方案有点复杂,但在其他方面则很简单
通常,with
子句不是解决方案的一部分;我包括它来测试查询。删除它并使用实际的表名和列名
with
inputs (id, ind) as (
select 1, 0 from dual union all
select 2, 0 from dual union all
select 3, 1 from dual union all
select 4, 0 from dual union all
select 5, 1 from dual union all
select 6, 0 from dual union all
select 7, 0 from dual
)
select id, ind, out
from inputs
match_recognize(
order by id
measures case classifier() when 'Z' then 0
when 'O' then count(*) - 1
else count(*) end as out
all rows per match
pattern ( Z* ( O | X ) )
define Z as ind = 0, O as ind != 0
);
ID IND OUT
---------- ---------- ----------
1 0 0
2 0 0
3 1 2
4 0 0
5 1 1
6 0 0
7 0 2
Oracle 12.1中引入的
match\u recognition
子句可以快速解决此类“行模式识别”问题。由于对ID=0的“最后一行”进行了特殊处理,解决方案有点复杂,但在其他方面则很简单
通常,with
子句不是解决方案的一部分;我包括它来测试查询。删除它并使用实际的表名和列名
with
inputs (id, ind) as (
select 1, 0 from dual union all
select 2, 0 from dual union all
select 3, 1 from dual union all
select 4, 0 from dual union all
select 5, 1 from dual union all
select 6, 0 from dual union all
select 7, 0 from dual
)
select id, ind, out
from inputs
match_recognize(
order by id
measures case classifier() when 'Z' then 0
when 'O' then count(*) - 1
else count(*) end as out
all rows per match
pattern ( Z* ( O | X ) )
define Z as ind = 0, O as ind != 0
);
ID IND OUT
---------- ---------- ----------
1 0 0
2 0 0
3 1 2
4 0 0
5 1 1
6 0 0
7 0 2
在ID=7下显示的2没有意义。您仅在零序列结束(附加到具有非零IND的ID)后显示计数,为什么输出的最后一行中的计数不同?@mathguy这是因为边缘情况,在结束之前有两个零,需要更改considered@user14999956 . . . “为什么不把计数放在所有行上呢?”戈登·林诺夫,怎么做?我没有单独的值来进行分区和计数。您在OUT下面显示的ID=7的2没有意义。您仅在零序列结束(附加到具有非零IND的ID)后显示计数,为什么输出的最后一行中的计数不同?@mathguy这是因为边缘情况,在结束之前有两个零,需要更改considered@user14999956 . . . “为什么不把计数放在所有行上呢?”戈登·林诺夫,怎么做?这两种解决方案都忽略了一个特殊要求,即如果最后一行的IND=0,则该行的输出必须显示该组的零计数。看看我对OP的问题和他的答案。此外,第二个查询不计算零,它计算组中的所有行(因此,除了修复“最后一行的IND=0”问题外,还必须修复计数-减去1)。这两种解决方案都忽略了一个特殊要求,即如果最后一行的IND=0,则该行的输出必须显示该组的零计数。看看我对OP的问题和他的答案。此外,第二个查询不计算零,它计算组中的所有行(因此,除了修复“最后一行的IND=0”问题外,还必须修复计数-减去1)。