在Oracle中它运作良好......
查询oracle是As Follows
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中需要一种替代方法
任何人都可以帮助...........
答案 0 :(得分:2)
适用于SQL Server 2005 +的SQL Server Engine blog有一种解决方法
不幸的是,它很长很复杂:我会给你留下链接,而不是试图让它适应你的查询......
答案 1 :(得分:1)
您可以创建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
}