【问题标题】:How to write the quantile aggregate function?如何编写分位数聚合函数?
【发布时间】:2011-12-01 07:36:27
【问题描述】:

我有下表:

CREATE TABLE #TEMP (ColA VARCHAR(MAX), ColB VARCHAR(MAX), Date date, Value int)

INSERT INTO #TEMP VALUES('A','B','7/1/2010','11143274')
INSERT INTO #TEMP VALUES('A','B','7/1/2010','13303527')
INSERT INTO #TEMP VALUES('A','B','7/1/2010','17344238')
INSERT INTO #TEMP VALUES('A','B','7/1/2010','13236525')
INSERT INTO #TEMP VALUES('A','B','7/1/2010','10825232')
INSERT INTO #TEMP VALUES('A','B','7/1/2010','13567253')
INSERT INTO #TEMP VALUES('A','B','7/1/2010','10726342')
INSERT INTO #TEMP VALUES('A','B','7/1/2010','11605647')

INSERT INTO #TEMP VALUES('A','B','7/2/2010','13236525')
INSERT INTO #TEMP VALUES('A','B','7/2/2010','10825232')
INSERT INTO #TEMP VALUES('A','B','7/2/2010','13567253')
INSERT INTO #TEMP VALUES('A','B','7/2/2010','10726342')
INSERT INTO #TEMP VALUES('A','B','7/2/2010','11605647')
INSERT INTO #TEMP VALUES('A','B','7/2/2010','17344238')
INSERT INTO #TEMP VALUES('A','B','7/2/2010','17344238')
INSERT INTO #TEMP VALUES('A','B','7/2/2010','17344238')

SELECT * FROM #TEMP

DROP TABLE #TEMP

R(一个统计软件)中,为了计算最后一列的第95个百分位值,我正在做这样的事情:

ddply(data, c("ColA", "ColB", "Date"), summarize, Value95=quantile(Value, 0.95))

输出如下:

A B 2010-07-01 16022293
A B 2010-07-02 17344238

所有这一切都是对ColAColBDate 执行GROUP BY 操作并应用聚合函数quantile 函数。到目前为止一切都很好,但我应该有办法在 SQL Server 中执行此操作,因为这是一个可以在 SQL 中干净地完成的聚合操作,当数据量达到数百万时,我真的想在 SQL 中执行此操作而不是统计软件。

我的问题是我找不到编写分位数函数本身的好方法。我尝试使用 NTILE,但是当特定 GROUP BY 下的行数小于 100 时,使用 NTILE(100) 没有意义。有没有好的方法来做到这一点?

更新:如果有帮助,R 的更多输出:

> quantile(c(1,2,3,4,5,5), 0.95)
95% 
  5 
> quantile(c(1,2,3,4,5,5), 0.0)
0% 
 1 
> quantile(c(1,2,3,4,5,5), 1.0)
100% 
   5 
> quantile(c(1,2,3,4,5,5), 0.5) // MEDIAN
50% 
3.5 

【问题讨论】:

  • 这里需要什么公式?您的示例表有 8 个不同的值。最低的 1 个百分位 0 和最高的 100 个百分位,其他 6 个分布均匀还是计算方式不同?
  • 是的。我认为这里就是这种情况。据我了解,实际上R 正在做一些插值以获得第 95 个百分位数。我可以给你指出这个:stackoverflow.com/questions/95007/… 吗?因为我确信自己试图解释这一点会引发更多的问题而不是答案。如果有帮助,请从 R 中添加一些输出。

标签: sql sql-server sql-server-2008 r


【解决方案1】:

当数据在数百万的量级时,我真的很想在 SQL 中做这个,而不是一个统计软件。

您是否尝试过 R 中的 data.table 包?请参阅 this article 比较 ddply 和 data.table。

【讨论】:

    【解决方案2】:

    我会这样做(代码有点乱)

    CREATE TABLE #TEMP (ColA VARCHAR(MAX), ColB VARCHAR(MAX), Date date, Value int)
    
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','11143274')
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','13303527')
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','17344238')
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','13236525')
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','10825232')
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','13567253')
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','10726342')
    INSERT INTO #TEMP VALUES('A','B','7/1/2010','11605647')
    
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','13236525')
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','10825232')
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','13567253')
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','10726342')
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','11605647')
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','17344238')
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','17344238')
    INSERT INTO #TEMP VALUES('A','B','7/2/2010','17344238')
    
    INSERT INTO #TEMP VALUES('A','c','7/2/2010','1')
    INSERT INTO #TEMP VALUES('A','c','7/2/2010','2')
    INSERT INTO #TEMP VALUES('A','c','7/2/2010','3')
    INSERT INTO #TEMP VALUES('A','c','7/2/2010','4')
    INSERT INTO #TEMP VALUES('A','c','7/2/2010','5')
    INSERT INTO #TEMP VALUES('A','c','7/2/2010','5')
    
    
    declare @perc decimal(6,5)
    set @perc = 1.0
    
    select cola, colb,date, sum(value)/convert(decimal,count(value)) from (
    
    select 
       row_number() OVER(partition by x.cola, x.colb, x.date order by x.value) as id,
       x.*,
       convert(int, y.zz) as j,
       case when (y.zz - convert(int, y.zz)) = 0 then convert(int, y.zz) + 1 else convert(int, y.zz) end as k,
       y.zz
    from 
    #temp x join 
    (
       SELECT 
          cola, 
          colb, 
          date, 
          count(*)*@perc zz 
       FROM 
          #TEMP  
       group by 
          cola, 
          colb, 
          date
    )y on x.cola = y.cola and x.colb = y.colb and x.date = y.date
    
    )xxx where id = j or id = k
    group by cola, colb, date
    

    还有更多计算方法(就所使用的方法而言)。我使用的是 SAS 5 (R-2) 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-23
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多