NTILE 仅适用于非零值
NTILE only for values different from zero
我有一列有很多零,我只想将非零值放入 N 组(大约)大小相等。所有零值都应获得组号 0。是否有一种优雅的方法可以做到这一点?
我的第一个方法是使用下面代码中的 ntile_v2
,但是这样 bin 编号就不会以 1 开头,我也不会得到 N 个 bin。
with sample_data as
(select
rownum as id,
case when rownum <= 50 then 0 else rownum end as value
from xmltable('1 to 100')
)
select
id,
value,
ntile(50) over (order by value) as ntile_v1,
case when value = 0 then 0 else ntile(50) over (order by value) end as ntile_v2
from sample_data
order by id;
一个解决方案是将非零值放入单独的 CTE,计算那里的图块,然后返回:
with sample_data as
(select
rownum as id,
case when rownum <= 50 then 0 else rownum end as value
from xmltable('1 to 100')
)
, sample_data_not_zero as
(select
id,
value,
ntile(50) over (order by value) as ntile_v3
from sample_data
where value <> 0
)
select
sd.id,
sd.value,
nvl(sdnz.ntile_v3, 0) as ntile_v3
from
sample_data sd
left outer join
sample_data_not_zero sdnz on sd.id = sdnz.id
order by id;
不幸的是,我必须为许多不同的列计算这个,我想知道是否有更短的解决方案。
除了当前的 case 表达式之外,您还可以根据零对 ntile
与 non-zero 进行分区:
case
when value = 0 then 0
else ntile(50) over (partition by case when value = 0 then 0 else 1 end order by value)
end as ntile_v3
这似乎与您的 union
查询得到相同的结果。
我有一列有很多零,我只想将非零值放入 N 组(大约)大小相等。所有零值都应获得组号 0。是否有一种优雅的方法可以做到这一点?
我的第一个方法是使用下面代码中的 ntile_v2
,但是这样 bin 编号就不会以 1 开头,我也不会得到 N 个 bin。
with sample_data as
(select
rownum as id,
case when rownum <= 50 then 0 else rownum end as value
from xmltable('1 to 100')
)
select
id,
value,
ntile(50) over (order by value) as ntile_v1,
case when value = 0 then 0 else ntile(50) over (order by value) end as ntile_v2
from sample_data
order by id;
一个解决方案是将非零值放入单独的 CTE,计算那里的图块,然后返回:
with sample_data as
(select
rownum as id,
case when rownum <= 50 then 0 else rownum end as value
from xmltable('1 to 100')
)
, sample_data_not_zero as
(select
id,
value,
ntile(50) over (order by value) as ntile_v3
from sample_data
where value <> 0
)
select
sd.id,
sd.value,
nvl(sdnz.ntile_v3, 0) as ntile_v3
from
sample_data sd
left outer join
sample_data_not_zero sdnz on sd.id = sdnz.id
order by id;
不幸的是,我必须为许多不同的列计算这个,我想知道是否有更短的解决方案。
除了当前的 case 表达式之外,您还可以根据零对 ntile
与 non-zero 进行分区:
case
when value = 0 then 0
else ntile(50) over (partition by case when value = 0 then 0 else 1 end order by value)
end as ntile_v3
这似乎与您的 union
查询得到相同的结果。