[转载]我们这样做报表之蚂蚁战术
常有同学问起,XCode能够通过分表分库做海量数据CURD,统计报表怎么做?
其实这个超级简单!!!
很多人习惯了用group by,很慢,非常慢,并且不适用于XCode的分表分库。
那么,我们新生命团队是怎么做的呢?
我们有一个类似于蚂蚁搬家的蚂蚁战术,根本不在乎有多少数据,不在乎如何分表分库!
public static void ProcessAll(Int32 year, Int32 month) { if (month < 0) { for (int i = 0; i < 13; i++) { ProcessAll(year, i); } return; } var list = new List<Int32>(); foreach (var item in AdminHelper.Factory.Cache.Entities) { var id = (Int32)item["ID"]; if (!list.Contains(id)) list.Add(id); } Process(list.ToArray(), year, month); // 统计全部 Process(null, year, month); } public static void Process(Int32 id, Int32 year, Int32 month) { if (id <= 0) throw new ArgumentNullException("salesmanid"); Process(new Int32[] { id }, year, month); } public static void Process(Int32[] ids, Int32 year, Int32 month) { if (year < 0) throw new ArgumentNullException("year"); if (month < 0) throw new ArgumentNullException("month"); // 找出来哪个没有的 var ds = new List<Int32>(); if (ids != null && ids.Length > 0) ds.AddRange(ids); var istotal = ds.Count > 0; var list = SalesOrder.SearchStatistics(ids, year, month, SalesOrder._.SalesmanID); if (list.Count < 1) return; using (var trans = Meta.CreateTrans()) { foreach (var sd in list) { // 跳过无数据记录 if (sd.Status < 1) continue; // 找出来哪个没有的 if (ds.Contains(sd.SalesmanID)) ds.Remove(sd.SalesmanID); var cs = FindBySalesmanIDAndYearAndMonth(sd.SalesmanID, year, month); if (cs == null) { cs = new SalesmanStatistics(); cs.SalesmanID = sd.SalesmanID; cs.Year = year; cs.Month = month; } // 验证销售员 if (!istotal) { var man = AdminHelper.FindByID(sd.SalesmanID); if (man != null) cs.Name = man.FriendName; } else cs.Name = "【所有】"; cs.Count = sd.Status; cs.Cost = sd.Cost; cs.Profit = sd.Profit; cs.PushMoney = sd.PushMoney; cs.LastID = sd.ID; cs.LastTime = sd.CreateTime; cs.Save(); } // 删除多余的 if (ds.Count > 0) { FindAll(_.SalesmanID.In(ds) & _.Year == year & _.Month == month, null, null, 0, 0).Delete(); } // 再查一次新客户 //exp &= SalesOrder._.IsNewCustomer == true; list = SalesOrder.SearchStatistics(ids, year, month, SalesOrder._.SalesmanID, true); if (list.Count > 0) { foreach (var sd in list) { // 跳过无数据记录 if (sd.Status < 1) continue; var cs = FindBySalesmanIDAndYearAndMonth(sd.SalesmanID, year, month); if (cs == null) { cs = new SalesmanStatistics(); cs.SalesmanID = sd.SalesmanID; cs.Year = year; cs.Month = month; } cs.NewCount = sd.Status; cs.NewCost = sd.Cost; cs.NewProfit = sd.Profit; cs.NewPushMoney = sd.PushMoney; cs.Save(); } } trans.Commit(); } }
上面是统计某个月所有销售员业绩的代码,计算以后就可以得到月度销售报表!
实际上,我们可以在用户查询数据或者查看月度报表的时候,开一个后台线程,默默的去执行这些统计函数。
这些函数的最大特点就是,逐步取出来数据,然后一个个实体对象累加,最后保存到统计表里面去!
用户查看统计报表的时候,实际上是直接从统计表里面拿数据。
有同学要问,这样岂不是拿不到最新的数据?
哦,恐怕是的!但是,你会在乎那么几秒钟的实时性吗?当你发现数据不够新的时候,也许等2秒钟后再点一次页面,已经是最新的了!
最最最重要的是:
蚂蚁战术,非常容易写,会C#就行,不用复杂SQL,不用存储过程。还可以跨表跨库跨服务器,还可以跨不同数据库类型……
End.
PS:这篇文章很好,Mark,感谢石头哥!
作者:VAllen
出处:http://www.cnblogs.com/vallen
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
唯有偏执者得以生存。
出处:http://www.cnblogs.com/vallen
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
唯有偏执者得以生存。