CASE函数
作用:
- 可以将查询结果集的某一列的字段值进行替换
- 它可以生成一个新列
- 相当于switch...case和 if..else
使用语法:
case 表达式/字段
when 值 then 自定义值
else
end as 别名
when 值 then:可以理解为当某个字段为某个值的时候,然后就返回自定义值将结果集的字段值进行替换
else:如果上面的when都不满足就执行else结果
常用用法一(case后面有字段或者表达式):
when关键字后面写固定值
case关键字后面如果有字段或者表达式,那么这种结构只能做等值判断,等值的意思是when关键字后面写了固定的值
示例图解:
注意:该方式不能用于判断null
常用方式二(case关键字后面没有字段或表达式):
when关键字后面写条件表达式
思考:
现在有个需求说,要求年龄字段这个人满足18岁或者年龄在某个范围,那么如果用上面说的等值判断,无法满足,因为字段要匹配的是一个范围
如果case关键字后面没有写字段或表达式,那么结构就相当于 if..elseif...else可以做范围判断,它可以使用null值判断
实例图解:
注意:
then 后面的值的类型 要与当前case范围内的保持一致
sql server——分组查询(方法和思想)
思想
先排序在汇总
sql server里分组查询通常用于配合聚合函数,达到分类汇总统计的信息。而其分类汇总的本质实际上就是先将信息排序,排序后相同类别的信息会聚在一起,然后通过需求进行统计计算。
使用GROUP BY进行分组查询
实例演示
--查询男女生的人数
在没有学习分组查询之前,我们可以安装常规的思路解决查询需求:
select count(*) from student where sex='男'
select count(*) from student where sex='女'
那么现在又要个需要时,查询每个班级的总人数
如果按照常规解决查询,那么我们应该思考的是:
1.每个班级,我们并不知道在表里有哪些班级,那么我们where 后的条件如何写?
2.如果该表里有1000个班级,那么我难道要写一千条where查询语句?
面对这样的问题 sql server为我们准备了Group by 关键字实现分组查询
在使用介绍Group by关键字之前,我们先来看看系统实现分组查询的原理和逻辑:
映射成SQL语句:
select sex ,count(*) as 人数 from student group by sex
这个简短的语句,经过上图的原理,应该要知道,第一步是先from查询表的所有信息,然后group by根据字段进行分组后在统计汇总
上面的案例是通过Count()函数进行统计,当然分组汇总还可以使用其他的聚合函数进行汇总。
使用GROUP BY 语句注意事项一:
图中使用查询语句,包含一个字段和一个聚合函数为什么会报错呢?
原因,我们把两个字段分开来查询:
总结:为了保证完整性,系统约定俗成,在使用了聚合函数的查询语句中,除了聚合函数,可以在查询列表上,要出现其他字段,那么该字段就必须为分组字段,而且该字段一定要跟随在GROUP BY关键字后面。
与聚合函数一起出现在select后面进行查询的列,只有两种可能性:被聚合 、被分组
多列分组查询
--实例需求,查询每一个班级,男女生的人数
分析:显然需求是两组,每一个班需要划分组,男女也需要分组
实现图解:
SQL语句:
select GradeId,sex,COUNT(*) from student group by GradeId,Sex order by GradeId
经验:搞清楚需要分几组,搞清楚分组的顺序,一轮一轮的分,系统是等分组之后才会进行汇总信息
使用HAVING子句
演示示例:--查询每一个班级男女生的人数,同时只需要显示人数数量超过3人的记录
分析:此查询显然是对上一个示例的多列分组进行筛选。
试在这学的知识范围内来解决此查询需求。。。。
一、那么就按照我们学的where来进行筛选
结果如图:
这个错误告诉了我们:where里面不能出现聚合函数作为条件,失败!
二、既然不能使用聚合函数,那就给聚合函数取一个别名,让它当做一个列
结果如图:
错误原因:原因是where是对源数据进行筛选的,也就是对from 后面的表进行筛选,既然是源数据,那么where去源数据表里找一个别名字段,怎么可能会有!所以才会报错
让我们来探讨一下,这里为什么不能使用where
1.需求是对分组之后的数据集进行筛选,where只针对数据表原始数据筛选
2.where关键字显然只能出现一次,而且根据查询的顺序,是先执行where条件筛选后得到的结果集,在进行的group by分组
解决办法,使用HAVING关键字:
HAVING核心:是对分组统计之后的结果集,进行数据的筛选
SQL语句:
select GradeId,sex,COUNT(*) as renshu from student group by GradeId,Sex having count(*)>=3 order by GradeId
where和having的不同:where是对原始数据进行筛选,having是对分组时候的数据进行筛选
查询语句的执行顺序
在这里引出查询机制里对查询语句里的关键字的执行顺序
查询关键字家族成员
select top/distinct 字段列表 from 表列表 where 筛选条件 group by 分组字段列表 having 对分组之后得到的结果集筛选 order by 排序字段列表
执行顺序:
1.from
2.where
3.group by
4.having
5.根据select 关键之后的要显示的字段,进行结果集显示
6.order by 对最终结果集进行排序
7.top/dictinct
ref和out
Ref 把值传递变成引用传递
当调用一个方法时,传入的参数是一个值类型,那么需要方法将这个传入的值类型的变量值改变受到影响,我们可以使用ref 关键字进行处理实现。
观察一:
结论:
根据值类型和引用类型的特点,值类型是赋值,是复制传递的是栈上存储的具体值信息,如图实参变量"a"将100赋值给方法形参"num"变量。那么值类型的改变只会影响值的本身,形参的改变没有形象到变量"a"。
加上ref修饰形参:
结论:
通过ref关键字,此时传递变量a的时候,实参把引用传给了形参,那么说明了这两个变量将指向同一个引用地址,变量num在方法中的改变会影响到变量a
输出结果:101
使用ref关键字的时候需要注意:
1.用了ref关键的方法,必须在参数列表上加上ref关键字,在调用该方法的时候也要加上ref关键字。
2.作为传入修饰了ref的方法的实参变量,必须赋初始值
作用总结:如果想使一个值类型的变量,通过传入一个方法进行改变,可以使用ref
OUT 让方法返回多个值
从语法规则上来讲,一个方法只能有一个返回值,如果return多个值简直是天方夜谭,如图:
通过out的方式实现:
static void Main(string[] args) { int a ; changeNum(out a); Console.WriteLine(a); //结果为101 } static stringchangeNum(out int num) { num = 100; num++; return "ok"; }
使用out关键字需要注意:
1.在方法定义和方法调用时,都要加上out关键字
2.方法参数列表上修饰了out关键字的变量,必须在方法体赋初始值,对于方法调用提供的实参变量可以不需要赋值。
面试题
ref与out的区别是什么?
使用ref的时候要传入相应方法的实参变量,必须赋值。而out在调用的时候只用声明,但是在方法内部,修饰了out形参必须赋值。
ref和out有着异曲同工之妙,都可以实现相同的功能,ref侧重于将值类型的值传递改变为引用传递,out侧重于对于一个方法返回多个值
一般处理程序结合反射技术统一执行客户端请求
思考:
在开发中,如果使用了模板技术+一般处理程序开发,应用中用户的请求可能在程序中都存在一个共性的操作。
例如,每当执行请求时要检查用户是否是登陆,请求时检查用户是否具有相应权限等等的共性的操作,我们不可能每个页面都写上对于操作,那样显然不符合面向对象的思想,存在大量冗余。
如何去解决呢?
解决思路:
- 创建一个父类实现IHttpHandler接口,让处理请求的一般处理程序实现这个接口,当一般处理程序接收到请求时,去统一执行父类里的ProcessRequest()方法。
- 客户端发出的请求,要约定俗成的带上一个action的参数,参数的值就是一般处理程序里要执行的方法。
- 当执行父类的ProcessRequest()方法时,利用反射获取当前一般处理程序的Type,前面说了action的值代表了当前请求执行的操作是什么,那么利用反射找到指定的方法然后执行它。
这样而来,可以让共性的操作在父类里完成,而具体的方法实现在子类里完成
范例代码:
子类
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using Blog.Common; 6 namespace Blog.UI.Article_category 7 { 8 /// <summary> 9 /// Handler1 的摘要说明 10 /// </summary> 11 public class Article_category_Controller : BaseHandler 12 { 13 14 //方法名都要约定:每个请求名都为action,action的值,都是一般处理程序的方法 15 public void list(HttpContext context) 16 { 17 string output= RazorHelper.RazorParsre("/Article_category/template/Blog_Category.cshtml"); 18 context.Response.Write(output); 19 } 20 21 22 23 } 24 }
父类
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Reflection; 5 using System.Web; 6 using System.Web.SessionState; 7 namespace Blog.UI 8 { 9 10 11 public class BaseHandler:IHttpHandler,IRequiresSessionState 12 { 13 14 //一般处理程序会第一个执行 ProcessRequest()方法,它自己没有,会找父类要,让父类统一来执行请求 15 public void ProcessRequest(HttpContext context) 16 { 17 18 /* 19 在处理请求操作之前,这里可以处理应用程序要遵循的共性操作 20 21 */ 22 23 24 25 26 //客户端每个请求约定俗成url带上一个参数叫action,action代表该请求执行什么操作 27 if (string.IsNullOrEmpty(context.Request["action"])) 28 { 29 return; 30 } 31 string action = context.Request["action"]; 32 33 //调用父类的方法,会是子类handler,利用反射获得类型 34 Type ty = this.GetType(); 35 //根据这个类型,找到和action同名对应的方法,也就是说用action找到当前请求要执行的方法 36 MethodInfo method = ty.GetMethod(action); 37 if (method!=null) 38 { 39 method.Invoke(this, new object[] { context }); //context是参数 40 return; 41 } 42 43 44 } 45 46 47 48 49 public bool IsReusable 50 { 51 get 52 { 53 return false; 54 } 55 } 56 57 58 59 } 60 61 62 63 64 }
遍历查询结果集,update数据
1 set rowcount 0 2 select NULL mykey, * into #mytemp from dbo.DIM_DISTRIBUTOR 3 4 set rowcount 1 5 update #mytemp set mykey = 1 6 7 declare @i int 8 set @i=1 9 while @@rowcount > 0 10 begin 11 set rowcount 0 12 select * from #mytemp where mykey = 1 13 14 declare @zj varchar(222) 15 select @zj=DISTRIBUTORID from #mytemp where mykey = 1 16 print @i 17 18 update DIM_DISTRIBUTOR set NAME='用户测试数据'+CAST(@i as varchar(222)) where DISTRIBUTORID=@zj 19 20 set @i=@i+1 21 delete #mytemp where mykey = 1 22 set rowcount 1 23 update #mytemp set mykey = 1 24 end 25 set rowcount 0
HBuilder设置APP状态栏
一、 前言
状态栏就是手机屏幕最顶部的区域,包括了:信号、运营商、电量等信息。通常APP都有属于自己的色调风格,为了达到整体视觉美观,通常会设置状态栏和标题栏的色调设置成一致。
图例:
二、状态栏状态类型
- 默认
- 变色(设置颜色)
- 透明(沉浸式)
- 消失(全屏)
三、状态栏变色
1.效果如图:
2.根据色调设置状态栏文字颜色,文字颜色只提供两种值:light(白色)、dark(黑色)
3.设置标题栏背景颜色
4.设置状态栏背景颜色,颜色值为16进制
示例代码:
1 <link href="css/mui.min.css" rel="stylesheet"/> 2 .mui-bar{ background-color: red;} 3 </link> 4 <script> 5 mui.plusReady(function(){ 6 plus.navigator.setStatusBarStyle('light'); 7 plus.navigator.setStatusBarBackground('#FF0000'); 8 }); 9 </script>
注意事项:
背景色终端支持仅:Android5及以上系统支持;iOS7.0及以上系统支持。
文字色终端支持仅:Android5只有小米和魅族支持,Android6及以上所有安卓支持;iOS7及以上支持。
四、状态栏透明(沉浸式)
1.效果如图:
(将背景图片和状态栏、标题栏贯通了)
2.运用实战(登录界面)
需求描述:将背景设置成图片,图片可以适应不同设备的分配率(响应式),将状态栏的背景设置成透明,背景图片覆盖状态栏至屏幕顶部。
<style> html,body{height: 100%;width: 100%;} body{ background:url(image/background.png)no-repeat; background-size:100% 100%; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image/background.png',sizingMethod='scale'); } </style>
mui.plusReady(function(){ plus.navigator.setStatusBarStyle('light'); });
"plus": { "statusbar": { "immersed": true } }
3.沉浸式延伸的问题
由于沉浸式模式是在manifest.json文件配置,作为了一个固定全局的设置,沉浸式的设置可能只是针对部分页面,那么对其他的页面都牵连了。
导致的效果如图:
(状态栏的高度被忽略)
解决代码:
mui.plusReady(function(){ plus.webview.currentWebview().setStyle({ statusbar:{background:'#ff0000'},top:0,bottom: 0 }); });
background属性,设置状态栏的背景色。
五、 全屏显示(没有状态栏)
在应用中可调用5+ API动态改变应用是否全屏显示的状态:
function fullscreen(){ // 设置应用全屏显示! plus.navigator.setFullscreen(true); } function unfullscreen(){ // 设置应用非全屏显示! plus.navigator.setFullscreen(false); } function isfullscreen(){ // 查询应用当前是否全屏显示! console.log( "是否全屏:"+(plus.navigator.isFullscreen()?"是":"否") ); }