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 2008 中恢复 SQL Server 2014 备份

Sql server2008! SQL server服务无法启动,并显示错误17113, 修复Sql server2008失败!

将 SQL Server 2008 r2 降级到 SQL Server 2008