数据库
首页 > 数据库> > 数据库学习(二)

数据库学习(二)

作者:互联网

本次学习过程中依然有许多细节需要注意,也让我复习到了许多已经忘却的知识,现总结如下。

1.WHERE和HAVING

这个知识点本不应该成为阻碍,但是由于最近没有细心学习sql,确实犯了一些小错误。总的来说,就是WHERE只能用于在表格中存在的字段的筛选,而HAVING可以用于一些自定义的字段。
比如,按照以下这段代码,是查询不出任何结果的,而且还会报错

select product_name,sale_price,purchase_price,(sale_price - purchase_price) as diffe
from product
where diffe >= 500;

在这里插入图片描述
而如果将WHERE改成HAVING,则可以达到目标。

select product_name,sale_price,purchase_price,(sale_price - purchase_price) as diffe
from product
having diffe >= 500;

在这里插入图片描述

2.三值逻辑与null

这其实算是sql中一个老生常谈的问题,却也是我一直把握不好的问题之一。现在我尝试说明我对null的理解。
首先,我们必须明确一件事,即sql中的布尔值并不只有true和false,它还有第三个值,即unknown,这种逻辑体系被称为三值逻辑。
三值逻辑应该算是sql的特色之一,至少在我的编程过程中还没有见到过另一种语言采用这种逻辑。既然要解释三值逻辑,就顺便提下大名鼎鼎的“四值逻辑”。即《SQL进阶教程》中说的“两种NULL”——“未知”(unknown)和“不适用”(not applicable)。
虽然听起来云里雾里,但是通过举一些生活中的常见例子还是可以理解的,比如“这个写博客的人会不会SQL”,人可以被分为两类,即会SQL的人和不会SQL的人,不了解我的人就是不知道我属于哪一类,这就叫做unknown,即未知。再举一个例子,“这篇博客会不会写SQL”,博客是不可能自己学会SQL的,这就是“不适用”。
截止到目前,未知指的就是不知道,但是可以通过一定的条件知道,比如只要和我一起写个图书管理系统就一定能知道我会不会SQL;而不适用指的就是,不管怎么样都不可能,一篇博客是不可能自己跳起来写SQL的。
算上true和false,此处一共提到了四种逻辑,在数据库的发展历程中,也的确有很多人提出过四值逻辑。但是最终经过各种考虑,SQL采用了三值逻辑,即true,false和unknown(NULL仅仅是一个标记),将未知和不适用归为了一类。
从现在开始,我们就可以引进另一个逻辑真值——unknown;必须理解的是,这里的unknown与上文所说的未知并不是一回事,前者是一个逻辑真值,即真的存在的逻辑值,而后者是NULL中的一种情况,是一个逻辑上的概念。到此,我们一共有了三个逻辑值,true,false,unknown
作为逻辑值,就一定会有与或非等逻辑运算,现盗图如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对于这个逻辑来说,我们应该注意以下几点:

接下来,我将结合SQL来说明三值逻辑。
我们应该了解的第一件事是,NULL不是一个值,即NULL不是一个逻辑真值,逻辑真值是unknown而不是NULL。这或许有点绕,但是我们依然要理解这个事实,即NULL本身不属于任何类型,它仅仅是作为一个代号,就像老叮当是我的外号,但是用老叮当这个名字去公安局一定查不到身份证号一样。所以在SQL中,无论是任何类型的值都不能直接与NULL做比较,因为这样做的结果一定是unknown。而数据库的查询结果一定是判断结果为true的行,逻辑为unknown的行是不可能返回的。所以,在数据库中我们应该使用is null,对于is null的理解是,我们不要将其分开看,而应该将其看作一个整体。
在这里插入图片描述
到现在为止,我们应该有能力解决这三个问题。
而再深入一步,我们应该看到因为第三种逻辑unknown的引入,数据库的世界会与我们真实世界的逻辑存在一定的不同,或者说,与我们通常习惯的逻辑存在一定差异。
所有例子都会从这张表中给出

比如,在我们的理解中,一件商品的价格一定大于等于5000或者小于5000,这几乎可以三岁小孩都知道的道理,按照这种逻辑,我们是可以查出所有的商品的。即

select * from product 
where purchase_price >= 5000 or purchase_price < 5000;

在这里插入图片描述
可以看出,这里只出现了六件商品,而实际上应该是八件商品。其原因就在于unknown的存在,由于purchase_price这一列中有两个NULL值,而大于等于或者小于等逻辑值与其判断后返回值都是unknown,所以这两行无法返回。对于三值逻辑,代码应该如下:

select * from product
where purchase_price >= 5000 or purchase_price < 5000 or purchase_price is null;

在这里插入图片描述
其实对于SQL来说,unknwon带来的逻辑混乱还有许多,所以在写一些代码的时候,必须仔细推敲,进行检查,才能达到自己的要求。
当然,三值逻辑和NULL背后的内容还有许多,远远比我所写的复杂,如果以后有时间,一定要再写一些关于这方面的内容。
3.关于NULL的排序
即使NULL是个符号,但是在排序的时候还会参与进来,真是个磨人的小妖精哈哈哈哈。
在MySQL中,NULL默认为最小值,即ASC排序时在最前面,DESC排序时在最后。
这就带来了一个问题,如果我DESC的时候就是想让NULL排在前面或者ASC的时候就是想让NULL排在最后面怎么办?
首先,我们要看看最正常的情况是什么样子

select * from product
order by purchase_price;

在这里插入图片描述
可以看出由于NULL默认最小,它排在了purchase_price的最前面,而如果想让它去后面也很简单,即通过“是否为NULL值”进行一次排序,代码如下

select * from product 
order by isnull(purchase_price),purchase_price;

在这里插入图片描述
之所以可以这么写,是因为在程序世界中,True通常为0,False通常为1,即这两个逻辑值之间也是可以排序的,这样就可以达到对NULL的排序效果。

以下为本次打卡的练习题:

--2.1 编写一条SQL语句,从product(商品)表中选取出“登记日期(regist在2009年4月28日之后”的商品,查询结果要包含product name和regist_date两列。
select product_name as "商品名",regist_date as "登记日期"
from product
where regist_date > '2009-04-28';


--2.2请说出对product 表执行如下3条SELECT语句时的返回结果。
SELECT *
  FROM product
 WHERE purchase_price = NULL;
SELECT *
  FROM product
 WHERE purchase_price <> NULL;
 SELECT *
  FROM product
 WHERE product_name > NULL;
 --由于与NULL进行比较,所以都是空集。
 
--2.3代码清单2-22(2-2节)中的SELECT语句能够从product表中取出“销售单价(saleprice)比进货单价(purchase price)高出500日元以上”的商品。请写出两条可以得到相同结果的SELECT语句。
select product_name,sale_price,purchase_price
from product
where sale_price >= purchase_price + 500; 

select product_name,sale_price,purchase_price,(sale_price - purchase_price) as diffe
from product
having diffe >= 500;

--2.4请写出一条SELECT语句,从product表中选取出满足“销售单价打九折之后利润高于100日元的办公用品和厨房用具”条件的记录。查询结果要包括product_name列、product_type列以及销售单价打九折之后的利润(别名设定为profit)。
select product_name,product_type,(sale_price * 0.9 - purchase_price) as profit,'日元' as '单位'
from product 
having profit > 100;

--2.5请指出下述SELECT语句中所有的语法错误。
SELECT product id,SUM(product name)
--本SELECT语句中存在错误。
  FROM product 
 GROUP BY product_type 
 WHERE regist_date > '2009-09-01';

--(1)不知道没有写下划线算不算语法错误哈哈哈哈
--(2)对字符串进行SUM()没有实际意义
--(3)GROUP BY字句应该在WHERE子句之后
--(4)封号没有用半角符号
--(5)在SELECT子句中不应该使用单独的product_id

--2.6请编写一条SELECT语句,求出销售单价(sale_price列)合计值是进货单价(purchase prilce列)合计值1.5倍的商品种类。执行结果如下所示。
select product_type,sum(sale_price) as sale_sum,sum(purchase_price) as pur_sum
from product
group by product_type
having sale_sum > pur_sum * 1.5
order by sale_sum desc;

--2.7此前我们曾经使用SELECT语句选取出了product(商品)表中的全部记录。当时我们使用了ORDERBY子句来指定排列顺序,但现在已经无法记起当时如何指定的了。请根据下列执行结果,思考ORDERBY子句的内容。
select * from product
order by if(isnull(regist_date),1,0) desc,regist_date desc,sale_price asc;

2.7图
本次习题质量非常高,十分感谢DataWhale团队的成员!

标签:purchase,product,unknown,数据库,sale,学习,NULL,price
来源: https://blog.csdn.net/m0_46388026/article/details/111298150