如何使用列值范围应用 NTILE(4)?

Posted

技术标签:

【中文标题】如何使用列值范围应用 NTILE(4)?【英文标题】:How to apply NTILE(4) using range of column values? 【发布时间】:2020-05-21 07:01:58 【问题描述】:

想使用NTILE 查看国家/地区的森林土地占土地总面积百分比的分布情况。我想使用的列中的值范围是从 0.00053 到非常接近 98.25,并且国家在该范围所暗示的四分位数中分布不均匀,即 0 到 25、25 到 50、50 到 75,以及大约 75 到 100。相反,NTILE 只是将表分成具有相同行数的四组。如何使用NTILE根据值分配分位数?

SELECT country, forest, pcnt_forest,
       NTILE(4) OVER(ORDER BY pcnt_forest) AS quartile
FROM percent_forest

【问题讨论】:

用您正在使用的数据库标记您的问题。 【参考方案1】:

您可以使用case 表达式:

select pf.*,
       (case when pcnt_forest < 0.25 then 1
             when pcnt_forest < 0.50 then 2
             when pcnt_forest < 0.75 then 3
             else 4
        end) as bin
from percent_forest pf;

或者,更简单,使用算术:

select pf.*,
       floor(pcnt_forest * 4) + 1 bin
from percent_forest pf;

我不会在本专栏中使用“四分位数”一词。四分位数意味着四个大小相等的 bin(或至少在给定重复值的情况下尽可能接近)。

【讨论】:

【参考方案2】:

WIDTH_BUCKET 函数非常适合这种情况:

WIDTH_BUCKET(Oracle) 可让您构造等宽直方图,其中直方图范围被划分为具有相同大小的区间。 (将此函数与创建等高直方图的 NTILE 进行比较。)

Oracle、Snowflake、PostgreSQL 等都支持...

您的代码:

SELECT country,  pcnt_forest
       ,WIDTH_BUCKET(pcnt_forest, 0, 1, 4) AS w
       ,NTILE(4) OVER(ORDER BY pcnt_forest) AS ntile  -- for comparison
FROM percent_forest
ORDER BY w

db<>fiddle demo

输出:

+----------+--------------+----+-------+
| COUNTRY  | PCNT_FOREST  | W  | NTILE |
+----------+--------------+----+-------+
| A        |         .05  | 1  |     1 |
| B        |         .06  | 1  |     1 |
| C        |         .07  | 1  |     2 |
| E        |         .49  | 2  |     2 |
| D        |         .51  | 3  |     3 |
| F        |         .96  | 4  |     3 |
| G        |         .97  | 4  |     4 |
| H        |         .98  | 4  |     4 |
+----------+--------------+----+-------+

【讨论】:

以上是关于如何使用列值范围应用 NTILE(4)?的主要内容,如果未能解决你的问题,请参考以下文章

NTILE的动态参数

如何将列值作为smartmatch的数字范围

如何连接列值在一定范围内的两个数据框?

Plotly:如何根据列值设置标记大小?

如何获得价值比多列值,而不是使用从SQL Server复合键字段

如何在 Laravel 刀片中使用动态表列值设置宽度