sql中连续变量的频率表?

2ul0zpep  于 2021-06-26  发布在  Impala
关注(0)|答案(2)|浏览(275)

我有一个连续变量sql表:

x
1   622.108
2   622.189
3   622.048
4   622.758
5   622.191
6   622.677
7   622.598
8   622.020
9   621.228
10  622.690
...

我试着得到一个简单的频率表,比如有3个桶,像这样:

bucket                  n
[621.228-621.738[       1
[621.738-622.248[       5
[622.248-622.758]       4

看起来很简单,但我无法在sql中实现它(我在cloudera impala引擎上运行它)。
我已经调查过了 dense_rank() 或者 ntile() 没有成功。
你知道吗?

n9vozmp4

n9vozmp41#

可以使用窗口函数将范围划分为三个相等的部分,然后使用算术:

select min_x + range * (row_number() over (order by min(x)) - 1) as bucket_hi,
       min_x + range * row_number() over (order by min(x)) as bucket_hi,
       count(*)
from (select t.*,
             min(x) over () as min_x,
             max(x) over () as max_x,
             0.000001 + max(x) over () - min(x) over () as range
      from t
     ) t
group by floor((x - min_x) / range)), min_x, range
js4nwp54

js4nwp542#

你的问题至少有两个问题:
您没有提供任何代码来向我们展示您所尝试的内容。有时候自己解决问题真的很好。尽管如此,我还是觉得这个问题很有趣,于是决定玩。
你的范围块重叠。例如,如果列表中的值是621.738,那么哪个bucket会包含它[621.228-621.738]或[621.738-622.248]?
我的回答至少有三个问题,所以我不希望你接受。然而,也许它会让你开始。希望,这个免责声明能让我不至于失望
答案是t-sql。抱歉,这是我必须处理的。
答案不是泛泛的。它总是创建三个而且只有三个桶。
仅当数据类型将结果限制为小数点后3位时,它才起作用。
记住,这只是一个可能的解决方案,在我看来,这是一个非常薄弱的解决方案。
有了这些免责声明,下面是我写的:

SELECT
       '[' + STR( RANGES.RANGESTART, 7, 3 )
           + ' - '
           + STR( RANGES.RANGEEND, 7, 3 ) + ']'    AS 'BUCKET'
      ,COUNT(*)                                    AS 'N'
  FROM
       ( SELECT
                VALS.MINVAL + (CAST( CNT.INC AS DECIMAL(7,3) ) * VALS.RANGEWIDTH) AS 'RANGESTART'
               ,CASE WHEN CNT.INC < 2
                     THEN VALS.MINVAL + (CAST( CNT.INC + 1 AS DECIMAL(7,3) ) * VALS.RANGEWIDTH) - 0.001
                     ELSE VALS.MINVAL + (CAST( CNT.INC + 1 AS DECIMAL(7,3) ) * VALS.RANGEWIDTH)
                END AS 'RANGEEND'
            FROM
                ( SELECT
                         MIN(CURVAL)                     AS 'MINVAL'
                        ,MAX(CURVAL)                     AS 'MAXVAL'
                        ,(MAX(CURVAL) - MIN(CURVAL)) / 3 AS 'RANGEWIDTH'
                    FROM
                        MYVALUE ) VALS
                        CROSS JOIN (VALUES (0), (1), (2) ) CNT(INC)
        ) RANGES
        INNER JOIN MYVALUE V
                ON V.CURVAL BETWEEN RANGES.RANGESTART AND RANGES.RANGEEND
GROUP BY
        RANGES.RANGESTART
       ,RANGES.RANGEEND
ORDER BY 1
;

在上面,您的值将位于myvalue表的curval列中。
祝你好运。我希望这对你有帮助。

相关问题