【问题标题】:Frequency table of continuous variable in SQL?SQL中连续变量的频率表?
【发布时间】:2020-06-23 13:36:47
【问题描述】:

我有一个连续变量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() 没有成功。

有什么想法吗?

【问题讨论】:

    标签: sql hiveql impala


    【解决方案1】:

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

    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
    

    【讨论】:

      【解决方案2】:

      你的问题至少有两个问题:

      1. 您没有提供任何代码来向我们展示您的尝试。有时候自己解决问题真的很好。不过,我发现这个问题很有趣,并决定玩。
      2. 您的范围块重叠。例如,如果您的列表中有值 621.738,哪个存储桶将包含它? [621.228-621.738] 还是 [621.738-622.248]?

      我的回答也至少有三个问题,所以我不希望你接受这个。但是,也许它会让你开始。希望这个免责声明能让我免于被否决。 :-)

      1. 答案在 T-SQL 中。抱歉,这是我必须处理的。
      2. 答案不是通用的。它始终创建三个且仅三个存储桶。
      3. 仅当数据类型将结果限制为小数点后 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 列中。

      祝你好运。我希望这对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-27
        • 2012-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-04
        相关资源
        最近更新 更多