准备着手,动态列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]