我有下表:
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
所有这一切都是在GROUP BY
,ColA
和ColB
上执行Date
操作并应用聚合函数quantile
函数。到目前为止这么好,但我应该有办法在SQL Server中执行此操作,因为这是一个可以在SQL中干净地完成的聚合操作,当数据大小为数百万时,我真的想在SQL中执行此操作而不是统计软件。
我的问题是我无法找到编写分位数函数本身的好方法。我尝试使用NTILE但是当特定NTILE(100)
下的行数小于100时使用GROUP BY
没有意义。有一个好方法吗?
更新: 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
答案 0 :(得分:2)
当数据大约为数百万时,我真的想在SQL中做这个而不是统计软件。
您是否尝试过R中的data.table包?请参阅this article将ddply与data.table进行比较。
答案 1 :(得分:1)
这是我将如何做到的(代码有点乱)
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)方法。