PCB SQL MS .net CLR 聚合函数joinString加排序实现

准备着手,动态列SQL查询,要实现动态列SQL,会运用到聚合函数,而SQL本身聚合函数有限,

无满足此用户任意字段组合变化,再加上工艺流程重复相同工序,如;沉铜1,沉铜2对应工序代码都是相同的

而通常聚合以后,数据排序工序失效,如果要实现,需采用低效的方式实现。

以其中一个:聚合函数joinString 为例说明,它是如何实现高效的

原来SQL实现:采用:FOR XML PATH ,为了达到高效,需建立临时表,这样效率才高一些,但这样实现比较呆呆的。

SELECT pdctno,techname,GlobalOrder INTO #ppeflow1
  FROM [FP_EMS_DB].[dbo].[V_PPEFlow]
WHERE pdctno IN (SELECT pdctno FROM #EDS_StateCam) AND  FlowLevel = 2

SELECT aa.pdctno
,(SELECT '' + bb.techname   + '--'  FROM #ppeflow1 bb where bb.pdctno = aa.pdctno ORDER BY  bb.globalOrder FOR XML PATH('')) flowString
  FROM #ppeflow1 aa
GROUP BY pdctno 

更改后SQL实现:这样一看简洁多了。

SELECT pdctno,FP_EMSDB_PUB.dbo.JoinString(techname,'--',GlobalOrder) flowString
  FROM [FP_EMS_DB].[dbo].[V_PPEFlow]
WHERE pdctno IN (
    SELECT pdctno FROM #EDS_StateCam
) AND  FlowLevel = 2
GROUP BY pdctno 

SQL实现效果

net实现代码:

 [Serializable]
    [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
      Format.UserDefined,
      IsInvariantToDuplicates = false,
      IsInvariantToNulls = true,
      IsInvariantToOrder = false,
      MaxByteSize = 8000,
      Name = "JoinString")]
    public struct UserJoinString : IBinarySerialize
    {
        private IList<stringOrder> ValueList;
        private string JoinString_;
        private string  Separate_;
        /// <summary>
        /// 查询处理器使用此方法初始化聚合的计算
        /// </summary>
        public void Init()
        {
            ValueList = new List<stringOrder>();
            Separate_ = "";
            JoinString_ = "";
        }
        /// <summary>
        /// 查询处理器使用此方法累计聚合值
        /// </summary>
        /// <param name="Value"></param>
        public void Accumulate(SqlString Value, SqlString Separate,SqlInt32 Orderno) //1
        {
            if (Separate_.Length == 0)
                Separate_ = Separate.ToString();
            ValueList.Add(new SQLClr.stringOrder() {  orderno = (int)Orderno , itemstring =Value.ToString() });
        }

        /// <summary>
        /// 查询处理器使用此方法合并聚合的多个部分计算的值
        /// </summary>
        /// <param name="Group"></param>
        public void Merge(UserJoinString Group) //无效  暂不用
        {
            //JoinString_.Append(Group.JoinString_ ); 
        }

        /// <summary>
        /// 此方法用于返回完成聚合计算的结果
        /// </summary>
        /// <returns></returns>
        public SqlString Terminate()
        {
            return new SqlString(JoinString_); //4
        }

        /// <summary>
        ////// </summary>
        /// <param name="r"></param>
        public void Read(System.IO.BinaryReader r) //3
        {
            JoinString_ = r.ReadString();
            Separate_ =r.ReadString();
        }

        /// <summary>
        ////// </summary>
        /// <param name="w"></param>
        public void Write(System.IO.BinaryWriter w)  //2
        {
            w.Write(string.Join(Separate_, ValueList.OrderBy(tt => tt.orderno).Select(tt => tt.itemstring).ToArray()));
            w.Write(Separate_);
       
        }
    }

    [Serializable]
    public class stringOrder
    {
        public string itemstring { get; set; }
        public int orderno { get; set; }
    }

聚合函数创建SQL:

--第一步:先删函数
--第二步:再更新DLL
--第三步:再创建函数
IF EXISTS(SELECT* FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[JoinString]') AND type = N'AF') 
DROP AGGREGATE[dbo].[JoinString]

ALTER  ASSEMBLY SQLfunctionAssembly
FROM 'D:\SQLClr.dll'      --改为自己C#写的dll路径填写
WITH PERMISSION_SET = UNSAFE;   


CREATE AGGREGATE[dbo].[JoinString]
(@Value[nvarchar](4000),      --聚合字符串
@Separate[nvarchar](20),      --分隔符
@Orderno    BIT               --排序号
)
RETURNS[nvarchar](4000)
EXTERNAL NAME[SQLfunctionAssembly].[SQLClr.UserJoinString]

猜你喜欢

转载自www.cnblogs.com/pcbren/p/9343602.html