sql server 2008中percentile_cont的替代方案

发布于 2025-01-06 00:18:23 字数 742 浏览 1 评论 0原文

在 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 中需要替代方法

任何人都可以帮忙...........

In Oracle it works well ......

Query for oracle is 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

But for SQL Server, I'm getting an error. Here's the query for 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

ERROR: Select could not be parsed correctly. Output could not be
generated.

I got to know that it can work properly in SQL Server 2012 but need an alternative way in SQL Server 2008

Can anybody help...........

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

忆依然 2025-01-13 00:18:23

SQL Server Engine 博客 适用于 SQL Server 2005+

不幸的是,它相当长且令人费解:我将给您留下链接,而不是尝试根据您的查询调整它...

There is a workaround on the SQL Server Engine blog that applies to SQL Server 2005+

Unfortunately, it's quite long and convoluted: I'll leave you with the link rather than attempt to adapt it for your query...

怂人 2025-01-13 00:18:23

您可以创建一个 CLR 聚合函数来实现相同的功能。唯一的缺点是您将不得不重新安排查询。我使用 CLR 实现了percentile_cont。请阅读此处了解如何创建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
}

You can create a CLR Aggregate function to implement the same. The only downfall is that you will have to re-arrange your query a bit. I implemented the percentile_cont using the CLR. Read here on how to create the CLR . Then you can use this code to get the same O/P as percentile_cont. Its a lot more easier than writing multiple statements.

You can definitely refine/tweak it a bit depending on your usage.

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文