前言

前面章节我们讲到了存储过程的基础用法,本章则将一个在项目中实际应用的场景。

在项目中经常会存在这样的需求,例如需要对明细列表进行按组、按级别、按人等进行统计,如果在附带列表的查询条件,又如何实现呢?

一般的思路是:先拿到明细数据,然后分别按照组,级别,人进行统计得到三个集合。

正确的做法应该是:客户需要什么维度的统计就获取当前维度的列表即可,在程序中要尽可能避免用不到的逻辑处理。

下面附上我的解决方案:

方案

我的方案是:利用存储过程将查询条件与统计维度的标示通过参数传递给存储过程,存储过程则负责返回统计后的结果。

下面附上实际案例:

存储过程代码

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语法高级应用之五:使用存储过程实现对明细多层次统计的更多相关文章

  1. Sql语法高级应用之三:存储过程

    一.存储过程概述 SQL Server中的存储过程是使用T_SQL编写的代码段.它的目的在于能够方便的从系统表中查询信息,或者完成与更新数据库表相关的管理任务和其他的系统管理任务.T_SQL语句是SQ ...

  2. Sql语法高级应用之七:如何在存储过程中使用事务

    普通事物: USE Wot_Inventory; GO BEGIN TRANSACTION tr; DECLARE @error INT; SET @error = 0; SELECT * FROM ...

  3. Sql语法高级应用之六:如何在Sql语句中如何使用TRY...CATCH

    TRY...CATCH使用范例 BEGIN TRY //逻辑语句块 END TRYBEGIN CATCH //Catch异常处理块 SET @msg = ERROR_MESSAGE(); PRINT ...

  4. Sql语法高级应用之二:视图

    SQL CREATE VIEW 语句 什么是视图? 在 SQL 中,视图是基于 SQL 语句的结果集的可视化的表. 视图包含行和列,就像一个真实的表.视图中的字段就是来自一个或多个数据库中的真实的表中 ...

  5. Sql语法高级应用之一:使用sql语句如何实现不同的角色看到不同的数据

    前言 在常见的管理系统中,通常都有这样的需求,管理员可以看到所有数据,部门可以看到本部门的数据,组长可以看到自己组的数据,组员只能看到自己相关的数据. 一般人的做法是,根据不同的角色通过if...el ...

  6. Sql语法高级应用之四:使用视图实现多表联合数据明细

    之前章节我们讲到:如果某个表的数据是多个表的联合,并且存在列与列的合并组成新列,用视图是最好的方案. 下面我分享两个个真实的SQL语句案例 USE Wot_Inventory GO FROM sys. ...

  7. SQL语法基础之高级应用

    SQL语法基础之高级应用 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.存储过程与函数 1>.CREATE PROCEDURE 用来创建存储过程 mysql> ? ...

  8. 高级数据查询SQL语法

    接上一篇关系数据库SQL之基本数据查询:子查询.分组查询.模糊查询,主要是关系型数据库基本数据查询.包括子查询.分组查询.聚合函数查询.模糊查询,本文是介绍一下关系型数据库几种高级数据查询SQL语法, ...

  9. SQL Server高级内容之case语法函数

    1.Case函数的用法  (1)使用类似:switch-case与if-else if. (2)语法: case [字段] when 表达式 then 显示数据 when 表达式 then 显示数据 ...

随机推荐

  1. SQL Server修改表结构后批量更新所有视图

    最近修改了数据库表结构,数据同步的时候出了问题,发现很多数据明明已经修改,但是通过视图筛选出来的还是原来的数据,所以怀疑应该是视图缓存了数据,在园子里找到下面的博文,在这里做个记录备忘. 原文链接:h ...

  2. Django学习---信号

    Django学习之信号 如果我想对所有在数据库创建数据的时候记录一条日志. 比如我们在django中往数据库中增加一条数据,希望生成一条操作日志,或者在数据保存和数据保存之后都保存一条操作日志,那我们 ...

  3. 运维基础工具tmux介绍及使用

    一.tmux是干什么的? 百度百科的解释很到位:tmux是指通过一个终端登录远程主机并运行后,在其中可以开启多个控制台的终端复用软件. 说白了就是复用软件,复用的什么软件呢? 你可以理解成复用shel ...

  4. MPI n 体问题

    ▶ <并行程序设计导论>第六章中讨论了 n 体问题,分别使用了 MPI,Pthreads,OpenMP 来进行实现,这里是 MPI 的代码,分为基本算法和简化算法(引力计算量为基本算法的一 ...

  5. springboot 默认错误处理--自定义

    1.在resoures下创建resoures/error文件夹 在其中自定义:404.html    403.html  500.html

  6. maven学习系列 之 常见问题

    1.新建的maven项目无法修改 Project Facets 的 Dynamic Web Module 版本 RE: 在工程目录下有一个.settings文件夹,打开org.eclipse.wst. ...

  7. 若p是与10互质的质数,则p-1个9能被p整除

    [若p是与10互质的质数,则k(p-1)个9能被p整除] 因为(p,10)=1,所以(p,10^k)=1.根据费马定理,10^(k*(p-1))-1|p. 而10^k*(p-1)-1是一个位数为(p- ...

  8. ADT下载地址整理(转)

    转自: http://blog.csdn.net/xqf222/article/details/9821971 参考下面文章 http://developer.android.com/tools/sd ...

  9. N 秒打开一个新窗口

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  10. 子串字谜substring anagrams

    [抄题]: 给定一个字符串 s 和一个 非空字符串 p ,找到在 s 中所有关于 p 的字谜的起始索引.字符串仅由小写英文字母组成,字符串 s 和 p 的长度不得大于 40,000.输出顺序无关紧要. ...