Sql语法高级应用之五:使用存储过程实现对明细多层次统计
前言
前面章节我们讲到了存储过程的基础用法,本章则将一个在项目中实际应用的场景。
在项目中经常会存在这样的需求,例如需要对明细列表进行按组、按级别、按人等进行统计,如果在附带列表的查询条件,又如何实现呢?
一般的思路是:先拿到明细数据,然后分别按照组,级别,人进行统计得到三个集合。
正确的做法应该是:客户需要什么维度的统计就获取当前维度的列表即可,在程序中要尽可能避免用不到的逻辑处理。
下面附上我的解决方案:
方案
我的方案是:利用存储过程将查询条件与统计维度的标示通过参数传递给存储过程,存储过程则负责返回统计后的结果。
下面附上实际案例:
存储过程代码
- USE Wot_Inventory;
- GO
- -- 判断要创建的存储过程名是否存在
- IF EXISTS
- (
- SELECT *
- FROM dbo.sysobjects
- WHERE id = OBJECT_ID(N'[Wot_Inventory].[dbo].[sp_nodeliverystatistics]')
- AND OBJECTPROPERTY(id, N'IsProcedure') = 1
- )
- -- 删除存储过程
- DROP PROC [sp_nodeliverystatistics];
- GO
- CREATE PROC [sp_nodeliverystatistics]
- (
- @ListName NVARCHAR(16), --列表名称
- @Nav NVARCHAR(16), --导航名称
- @Where VARCHAR(MAX), --查询条件
- @msg NVARCHAR(200) OUTPUT
- )
- AS
- BEGIN
- SET NOCOUNT ON;
- DECLARE @sqlStr NVARCHAR(MAX);
- BEGIN TRY
- IF @ListName <> ''
- AND @ListName IS NOT NULL
- AND @Nav <> ''
- BEGIN
- IF (@ListName = 'Agreed')
- BEGIN
- SET @sqlStr
- = N'SELECT ' + @Nav
- + ',COUNT(Id) Number,SUM(Receivable) TotalReceivable,AVG(Receivable) AvgReceivable,SUM(AgencyFund) TotalAgencyFund,AVG(Receivable) AvgAgencyFund FROM Wot_Inventory.dbo.NoDeliveryByDetailView WHERE 1 = 1';
- EXEC (@sqlStr + @Where + N' GROUP BY ' + @Nav + '');
- SET @msg = '列表统计成功';
- END;
- ELSE IF (@ListName = 'Immediate')
- BEGIN
- SET @sqlStr
- = N'SELECT ' + @Nav
- + ',COUNT(Id) Number,SUM(Receivable) TotalReceivable,SUM(AgencyFund) TotalAgencyFund,SUM(InsurreValue) TotalInsurreValue,SUM(FragileInsurreValue) TotalFragileValue FROM Wot_Inventory.dbo.NoDeliveryByDetailView WHERE 1 = 1';
- EXEC (@sqlStr + @Where + N' GROUP BY ' + @Nav + '');
- SET @msg = '列表统计成功';
- END;
- ELSE
- BEGIN
- SET @msg = '传递的参数不正确';
- END;
- END;
- ELSE
- BEGIN
- SET @msg = '传递的参数不正确';
- END;
- END TRY
- BEGIN CATCH
- SET @msg = ERROR_MESSAGE();
- PRINT @msg;
- END CATCH;
- PRINT @msg;
- END;
- GO
存储过程Sql
程序代码
- List<AgreedStatistics> dtoResult1 = new List<AgreedStatistics>();
- List<AgreedStatistics> dtoResult2 = new List<AgreedStatistics>();
- List<AgreedStatistics> dtoResult3 = new List<AgreedStatistics>();
- List<AgreedStatistics> dtoResult4 = new List<AgreedStatistics>();
- List<AgreedStatistics> dtoResult5 = new List<AgreedStatistics>();
- //按预约
- string sql = "EXEC Wot_Inventory.dbo.sp_nodeliverystatistics @ListName, @Nav, @Where, @msg OUT";
- var sqlwhere = "";
- sqlwhere = SetSqlWhere(sqlwhere, request, user, "Dtl");
- SqlParameter[] parms = new SqlParameter[]
- {
- new SqlParameter("@ListName","Agreed"),
- new SqlParameter("@Nav","AgreedDate"),
- new SqlParameter("@Where",sqlwhere),
- new SqlParameter("@msg",System.Data.SqlDbType.NVarChar,)
- };
- parms[].Direction = System.Data.ParameterDirection.Output;
- dtoResult1 = deliverRepository.ExecuteSql<AgreedStatistics>(sql, parms).OrderByDescending(t => t.TotalReceivable).ToList();
- msg = parms[].Value.ToString();
- dtoResult1.ForEach(t =>
- {
- t.Id = index1++;
- });
- //销售组
- string sql2 = "EXEC Wot_Inventory.dbo.sp_nodeliverystatistics @ListName, @Nav, @Where, @msg OUT";
- var sqlwhere2 = "";
- sqlwhere2 = SetSqlWhere(sqlwhere2, request, user, "Dtl");
- SqlParameter[] parms2 = new SqlParameter[]
- {
- new SqlParameter("@ListName","Agreed"),
- new SqlParameter("@Nav","SalesGroupName"),
- new SqlParameter("@Where",sqlwhere2),
- new SqlParameter("@msg",System.Data.SqlDbType.NVarChar,)
- };
- parms2[].Direction = System.Data.ParameterDirection.Output;
- dtoResult2 = deliverRepository.ExecuteSql<AgreedStatistics>(sql2, parms2).OrderByDescending(t => t.TotalReceivable).ToList();
- msg = parms2[].Value.ToString();
- dtoResult2.ForEach(t =>
- {
- t.Id = index2++;
- });
后台代码
前端效果
在当前案例中,我使用了缓存,在查询明细的同时,将所有维度的统计缓存起来,因为考虑到这个明细的列表不会产生太多的数据。这也是一种解决问题的思维,具体按实际情况而定。
PS:欢迎扫描下方二维码或点击链接,加入QQ群
Sql语法高级应用之五:使用存储过程实现对明细多层次统计的更多相关文章
- Sql语法高级应用之三:存储过程
一.存储过程概述 SQL Server中的存储过程是使用T_SQL编写的代码段.它的目的在于能够方便的从系统表中查询信息,或者完成与更新数据库表相关的管理任务和其他的系统管理任务.T_SQL语句是SQ ...
- Sql语法高级应用之七:如何在存储过程中使用事务
普通事物: USE Wot_Inventory; GO BEGIN TRANSACTION tr; DECLARE @error INT; SET @error = 0; SELECT * FROM ...
- Sql语法高级应用之六:如何在Sql语句中如何使用TRY...CATCH
TRY...CATCH使用范例 BEGIN TRY //逻辑语句块 END TRYBEGIN CATCH //Catch异常处理块 SET @msg = ERROR_MESSAGE(); PRINT ...
- Sql语法高级应用之二:视图
SQL CREATE VIEW 语句 什么是视图? 在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表. 视图包含行和列,就像一个真实的表.视图中的字段就是来自一个或多个数据库中的真实的表中 ...
- Sql语法高级应用之一:使用sql语句如何实现不同的角色看到不同的数据
前言 在常见的管理系统中,通常都有这样的需求,管理员可以看到所有数据,部门可以看到本部门的数据,组长可以看到自己组的数据,组员只能看到自己相关的数据. 一般人的做法是,根据不同的角色通过if...el ...
- Sql语法高级应用之四:使用视图实现多表联合数据明细
之前章节我们讲到:如果某个表的数据是多个表的联合,并且存在列与列的合并组成新列,用视图是最好的方案. 下面我分享两个个真实的SQL语句案例 USE Wot_Inventory GO FROM sys. ...
- SQL语法基础之高级应用
SQL语法基础之高级应用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.存储过程与函数 1>.CREATE PROCEDURE 用来创建存储过程 mysql> ? ...
- 高级数据查询SQL语法
接上一篇关系数据库SQL之基本数据查询:子查询.分组查询.模糊查询,主要是关系型数据库基本数据查询.包括子查询.分组查询.聚合函数查询.模糊查询,本文是介绍一下关系型数据库几种高级数据查询SQL语法, ...
- SQL Server高级内容之case语法函数
1.Case函数的用法 (1)使用类似:switch-case与if-else if. (2)语法: case [字段] when 表达式 then 显示数据 when 表达式 then 显示数据 ...
随机推荐
- 熟悉下apple 马甲包
一.什么是马甲包 马甲包是利用App store 规则漏洞,通过技术手段,多次上架同一款产品的方法.马甲包和主产品包拥有同样的内容和功能,除了icon和应用名称不能完全一致,其他基本一致. 二.为什么 ...
- flask的第一个例子
对django有了一些基础了解,现在看看flask,然后如果有时间可以看看 web.py 那么咱们开始flask的第一个例子 先安装flask pip install flask 看官方的教程 我也把 ...
- 读取和反序列化Hadoop二进制文件
目录 问题描述 反序列化代码 问题描述 Hadoop在运行MR时,经常要将一些中间结果存到本地,为了节省存储空间,Hadoop采用序列化机制(Hadoop的序列化机制和Java的有所不同)将数据保存为 ...
- 字段名与属性名不一致问题 通过resultMap解决
- s 销售视图数据
INSERT,需将公司ID匹对到以下EXCEL表 INSERT,需将公司ID匹对到以下EXCEL表 [Public] ConnectString=host="siebel://10.10.0 ...
- DNS开源服务器BIND最小配置详解
一,简介 相对于存储和大数据领域,CDN是一个相对小的领域,但行行出状元,BIND就是CDN领域的蝉联N届的状元郎.BIND是一款非常常用的DNS开源服务器,全球有90%的DNS用BIND实现.值得一 ...
- 5-math中函数汇总
math.h 数学函数库,一些数学计算的公式的具体实现是放在math.h里,具体有:1 三角函数double sin (double);double cos (double);double tan ( ...
- How to use mouse to moving windows of not have title bar?
How to use mouse to moving windows of not have title bar? #include "widget.h" #include < ...
- Golang之struct
1.用来定义复杂数据结构 2.struct里面可以包含多个字段(属性) 3.struct类型可以定义方法,注意和函数的区分. 4.struct类型是值类型 5.struct类型可以嵌套 6.Go语言没 ...
- Linux之chmod使用
Linux文件分三种身份和四中权限. u:文件的拥有者 g:文件所属的群组 o:其他用户 对于每个身份,又有四种权限,分别为: r:读取文件的权限(read) w:写入文件的权限(write) x:执 ...