SQL之case when then用法

 

创建表

create table users(id int,name varchar2(20),sex number);
 
insert into users(id,name) values(1,'张一');
insert into users(id,name,sex) values(2,'张二',1);
insert into users(id,name) values(3,'张三');
insert into users(id,name) values(4,'张四');
insert into users(id,name,sex) values(5,'张五',2);
insert into users(id,name,sex) values(6,'张六',1);
insert into users(id,name,sex) values(7,'张七',2);
insert into users(id,name,sex) values(8,'张八',1);
 
commit;

1、上表结果中的"sex"是用代码表示的,希望将代码用中文表示。可在语句中使用case语句:

select * from users;
select tt.* ,(case tt.sex when 1 then '男'
                      when 2 then '女'
                      else '空的'
                      end
                      )性别
           from users tt ;

2、如果不希望列表中出现"sex"列,语句如下:

select tt.id,tt.name ,(case tt.sex when 1 then '男'
                      when 2 then '女'
                      else '空的'
                      end
                      )性别
           from users tt ;

 

3、将sum与case结合使用,可以实现分段统计。

select sum(case when tt.sex = 1 then 1 else 0 end)男性,
       sum(case  when tt.sex = 2 then 1 else 0 end)女性,
       sum(case when tt.sex <>1 and tt.sex <>1 then 1 else 0 end)性别为空
       from users tt;

        男性         女性       性别为空
---------- ---------- ----------
         3          2          0
       select count(case when tt.sex = 1 then 1  end)男性,
       count(case  when tt.sex = 2 then 1  end)女性,
       count(case when tt.sex <>1 and tt.sex <>1 then 1  end)性别为空
       from users tt;

3.1、这里发现了一个错误 性别为空的为0 why? 不是3吗?

 t-sql 三个用于查询的筛选器
on  第一个
where  第二个
having 第三个

在SQL中,逻辑表达式的可能值为True False Unknown,称为三值逻辑
当比较丢失值和另一个值,逻辑结果为Unknown,例如:null>42
所有的筛选器都把Unknown 当做Fasle 处理
但是Check 约束会把Unknown当做True处理
而唯一约束,排序操作和分组操作认为两个Null值是相等的
如果表中有一列定义了唯一约束,将无法向表内插入该值为Null的两行
Group by 子句把所有Null值分到一组
Order by 子句把所有Null值排列在一起.


(2)应用ON筛选器(联接条件) 说到这里,首先得说下 SQL用于查询的有三个筛选器,分别是ON,where,having。 这里的ON筛选器就是用VTB1作为输入,再利用ON后面的联结条件进行筛选,生成VTB2。 sql编程第二特征:三值逻辑:它其实就是所谓的TRUE FALSE UNKOWN 主要来说这个UNKOWN 它这逻辑值和NULL在一起就会”出事“。凡是NULL参与的比如 NULL>42, NULL-8>9 这些结果都是UNKOWN UNKOWN 的逻辑结果在不同的环境下是被不同的方式处理的:如 在三个筛选器上,它是会被当做FALSE处理; 在CHECK约束上是会被当成TRUE来处理,check(col>8) 你插入的COL为NULL,因为NULL>8 的结果不就是UNKOWN ,所以是可以插入的。 在筛选器上的2个NULL比较将是FALSE 但是在UNIQUE约束,分组,排序上2个NULL是等价的。  
算术运算
如果算术表达式的任一输入为空,则该算术表达式(涉及诸如 +、-、* 或 / 的算术运算)结果为空。

例:如果查询中有一个表达式是r.A + 5, 并且对于关系中某个特定的元组, r.A为空,那么对此元组来说,该表达式的结果也为空。

比较运算
SQL将涉及空值的任何比较运算的结果视为unknown(既不是谓词is null,也不是is not null)。unknown是在SQL中除true和false之外的第三个逻辑值。

补充:由于在where子句的谓词中可以对比较结果使用诸如and、or和not的布尔运算,将布尔运算扩展到可以处理unknown值,运算结果如下:

and:true and unknown = unknown, false and unknown = false, unknown and unknown = unknown
or:true or unknown = true, false or unknown = unknown, unknown or unknown = unknown
not:not unknown = unknown
可以验证,如果r.A为空,那么"1 < r.A" 和 "not (1 < r.A)"的结果都为unknown。

"null = null"会返回unknown,而不是true。

 

select  (case when tt.sex <>1 and tt.sex <>2 then 1  end)性别为空
       from users tt;

  

解释: sex=1 时候 不符合条件 1<>1 ,sex=2 时候 2<>2 不符合条件,为null的时候 unknown 筛选器当做false处理,所以,都不符合条件,不能设置为1,设置为null.

  

这里就能解释了 

       select  count(case when tt.sex <>1 and tt.sex <>2 then 1  end)性别为空
       from users tt; //结果为0

 解释: tt.sex <>1  为null<>1 为unkown  , unknown and unknown 为unkonwn 被选择器when 当做fasle处理,被筛下丢弃,所以结果为0

       select  (case when tt.sex <>1 and tt.sex <>2 then 1  end)性别为空
       from users tt;

 所以最后对null的判断不对,改为:select count(case when tt.sex is null then 1 end)性别为空 from users tt;

SqlServer mysql 按月统计所有部门案例:

以订单统计为例,前端展示柱状图(Jquery统计):

表及主要字段描述如下;表名:Orders
1.日期CreateTime
2.金额Amount
3.用户UserID

情况一:
根据部门统计某一年每月销量(查询一个部门月统计)

1)直接在SQL语句中判断每月信息,好处,前台直接调用;坏处,性能不高。

SQL语句:

SELECT 
SUM(CASE WHEN MONTH(s.CreateTime) = 1 THEN s.Amount ELSE 0 END) AS '一月',
SUM(CASE WHEN MONTH(s.CreateTime) = 2 THEN s.Amount ELSE 0 END) AS '二月',
SUM(CASE WHEN MONTH(s.CreateTime) = 3 THEN s.Amount ELSE 0 END) AS '三月',
SUM(CASE WHEN MONTH(s.CreateTime) = 4 THEN s.Amount ELSE 0 END) AS '四月',
SUM(CASE WHEN MONTH(s.CreateTime) = 5 THEN s.Amount ELSE 0 END) AS '五月',
SUM(CASE WHEN MONTH(s.CreateTime) = 6 THEN s.Amount ELSE 0 END) AS '六月',
SUM(CASE WHEN MONTH(s.CreateTime) = 7 THEN s.Amount ELSE 0 END) AS '七月',
SUM(CASE WHEN MONTH(s.CreateTime) = 8 THEN s.Amount ELSE 0 END) AS '八月',
SUM(CASE WHEN MONTH(s.CreateTime) = 9 THEN s.Amount ELSE 0 END) AS '九月',
SUM(CASE WHEN MONTH(s.CreateTime) = 10 THEN s.Amount ELSE 0 END) AS '十月',
SUM(CASE WHEN MONTH(s.CreateTime) = 11 THEN s.Amount ELSE 0 END) AS '十一月',
SUM(CASE WHEN MONTH(s.CreateTime) = 12 THEN s.Amount ELSE 0 END) AS '十二月'
FROM Orders AS s
WHERE YEAR(s.CreateTime) = 2014 

 

一月    二月    三月    四月    五月    六月    七月    八月    九月    十月    十一月    十二月
0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    0.00    741327.00    120505.00    0.00

2)统计出数据库里有值的月份,再前端逻辑判断其他月份补0

SQL语句:

SELECT UserID, MONTH(CreateTime) as 月份, SUM(Amount) as 统计
  FROM Orders
 WHERE YEAR(CreateTime) = 2014 -- 这里假设你要查 2014年的每月的统计。
--其他条件
 GROUP BY UserID, MONTH(CreateTime)

  

参考:https://www.cnblogs.com/qlqwjy/p/7476533.html  

atzhang 

posted @ 2020-07-13 14:47  张艳涛&java  阅读(1062)  评论(0编辑  收藏  举报