sql server 2008 中 percentile_cont 的替代方案
Posted
技术标签:
【中文标题】sql server 2008 中 percentile_cont 的替代方案【英文标题】:Alternative for percentile_cont in sql server 2008 【发布时间】:2012-02-14 12:09:25 【问题描述】:在 Oracle 中它运行良好......
oracle的查询如下
Select distinct channel_id, position_id,datamonth,
percentile_cont(.9) within group (order by TRIM_PRE_ELIG_PAY)
over (partition by channel_id, position_id, datamonth) as TRIM_PRE_ELIG_PAY_90th_PERC
from Tablename
但是对于 SQL Server,我遇到了错误。这是 SQL Server 2008 的查询:
Select
distinct channel_id,
position_id, datamonth,
percentile_cont(.9) within group (order by TRIM_PRE_ELIG_PAY)
over (partition by channel_id) as TRIM_PRE_ELIG_PAY_90th_PERC
from table
错误:无法正确解析选择。无法输出 生成。
我知道它可以在 SQL Server 2012 中正常工作,但在 SQL Server 2008 中需要另一种方式
任何人都可以帮忙............
【问题讨论】:
【参考方案1】:SQL Server Engine blog 上有一个适用于 SQL Server 2005+ 的解决方法
不幸的是,它很长而且令人费解:我会把链接留给您,而不是尝试根据您的查询对其进行调整...
【讨论】:
链接已损坏。【参考方案2】:您可以创建一个 CLR 聚合函数来实现相同的功能。唯一的缺点是您将不得不重新安排您的查询。我使用 CLR 实现了 percentile_cont。阅读here,了解如何创建 CLR。然后您可以使用此代码获得与 percentile_cont 相同的 O/P。它比编写多个语句要容易得多。
您绝对可以根据您的使用情况对其进行一些细化/调整。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections.Generic;
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
Format.UserDefined,
IsInvariantToDuplicates = false,
IsInvariantToNulls = false,
IsInvariantToOrder = false,
MaxByteSize = 8000)]
public struct Percentile_Cont : IBinarySerialize
//Variables to hold the values;
private List<decimal> _list;
private decimal _percentile;
public void Init()
_list = new List<decimal>();
_percentile = new decimal();
public void Accumulate(SqlDecimal value,SqlDecimal percentile)
if (!value.IsNull)
_list.Add(value.Value);
_percentile = (decimal)percentile;
///
/// Merge the partially computed aggregate with this aggregate.
///
/// The other partial results to be merged
public void Merge(Percentile_Cont group)
this._list.AddRange(group._list.ToArray());
///
/// Called at the end of aggregation, to return the results.
///
/// The percentile of all inputted values
public SqlDecimal Terminate()
if (_list.Count == 0)
return SqlDecimal.Null;
_list.Sort();
if (_percentile < 0 || _percentile >= 1)
return SqlDecimal.Null;
var index =
(int) Math.Ceiling
(_percentile * _list.Count + 0.5m);
if(index > _list.Count)
index = index - 1;
return _list[index-1];
#region IBinarySerialize Members
public void Read(System.IO.BinaryReader binaryReader)
int cnt = binaryReader.ReadInt32();
this._list = new List<decimal>(cnt);
this._percentile = new decimal();
for (int i = 0; i < cnt; i++)
this._list.Add(binaryReader.ReadDecimal());
this._percentile = binaryReader.ReadDecimal();
public void Write(System.IO.BinaryWriter binaryWriter)
binaryWriter.Write(this._list.Count);
foreach (decimal d in this._list)
binaryWriter.Write(d);
binaryWriter.Write(_percentile);
#endregion
【讨论】:
以上是关于sql server 2008 中 percentile_cont 的替代方案的主要内容,如果未能解决你的问题,请参考以下文章
为啥安装的SQL SERVER 2008中SQL SERVER 服务只有1个
安装SQL SERVER 2008,出现“查找sql server 2008安装媒体”的问题
如何在 SQL Server 2008 中恢复 SQL Server 2014 备份
Sql server2008! SQL server服务无法启动,并显示错误17113, 修复Sql server2008失败!