Monday, July 4, 2016

数据库手札2 16/7/4





使用WHERE子句和GROUP BY 子句进行聚合处理
SELECT <列名1>, <列名2>, <列名3> ……
FROM <表名>
WHERE
GROUP BY <列名1>, <列名2>, <列名3> ……;
Eg:
SELECT shiire_tanka, COUNT(*)
FROM Shohin
WHERE shohin_bunrui = ‘衣服
GROUP BY shiire_tanka;
GROUP BY WHERE并用时,SELECT语句的执行顺序如下:
FROM->WHERE->GROUP BY->SELECT
这与3-2中提到的书写语句的顺序(SELECT-> FROM->WHERE->GROUP BY)是不同的

**TIP: 与聚合函数和GROUP BY子句有关的常见错误:
常见错误1. SELECT子句中书写了多余的列
原因是:在使用COUNT这样的聚合函数时,SELECT子句中的元素有严格的限制。在使用聚合函数时,SELECT子句中只能存在以下三种元素:
1.       常数
2.       聚合函数
3.       GROUP BY 子句中指定的列名(也就是聚合键)
而我们经常容易犯的错误是: 把聚合键之外的列名写在SELECT子句中

常见错误2. GROUP BY子句中写了列的别名
原因是:SELECT子句中的项目可以通过AS关键字来指定别名,但是在GROUP BY子句中是不能使用别名的。
错误示例:
SELECT shohin_bunrui AS sb, COUNT(*)
  FROM Shohin
GROUP BY sb;
会有这些错误的内在原因其实就是子句的执行顺序。

常见错误3. 以为GROUP BY子句的结果是排序的
     实际上GROUP BY子句的结果的显示是无序、完全偶然的。如果想要按照某种特定顺序进行排序的话,需要在SELECT语句中进行指定。

常见错误4. WHERE子句中使用聚合函数
错误示例:
SELECT shohin_bunrui, COUNT(*)
  FROM Shohin
WHERE COUNT(*) = 2
GROUP BY shohin_bunrui;
实际上,只有SELECT子句、HAVING子句和ORDER BY子句中能够使用COUNT等聚合函数。

3-3 为聚合结果指定条件
HAVING子句
WHERE子句只能指定记录(行)的条件,而不能用来指定组的条件。因此对集合指定条件就需要HAVING子句。
SELECT <列名1>, <列名2>, <列名3>, ……
FROM <表名>
GROUP BY <列名1>, <列名2>, <列名3>, ……
HAVING <分组结果对应的条件>
HAVING子句必须写在GROUP BY子句之后。其在DBMS内部的执行顺序也排在GROUP BY子句之后。所以使用HAVING子句时SELECT语句的顺序:
SELECT->FROM->WHERE->GROUP BY->HAVING

Eg: 从通过商品种类进行聚合分组后的结果中,取出“包含数据的行数为2行”的组
SELECT shohin_bunrui, COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui
HAVING COUNT(*) = 2;

**HAVING 子句和包含GROUP BY 子句时的SELECT子句一样,能够使用的要素有一定的限制。限制的内容也是完全相同的:
1.       常数
2.       聚合函数
3.       GROUP BY 子句中指定的列名(也就是聚合键)

** 对于聚合键所对应的条件,它既可以写在HAVING子句中,也可以写在WHERE子句中的这种情况,写在WHERE子句中更合适。原因有两个:其一,WHEREHAVING两者含义不同,WHERE子句 = 指定行对应的条件,HAVING子句 = 指定组所对应的条件。 其次,WHERE子句的执行速度较HAVING子句要更快一些。



3-4 对查询结果进行排序
   ORDER BY子句
   通常,从表中抽取数据时,如果没有特别指定顺序,最终排列顺序便无从得知。为了避免混乱的结果,便需要通过SELECT语句末尾添加ORDER BY 子句来明确指定排列顺序。
语法如下:
SELECT <列名1>, <列名2>, <列名3>, ……
FROM <表名>;
ORDER BY <排序基准列1>, <排序基准列2>, ……
Eg:
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka;

不论何种情况,ORDER BY子句都需要写在SELECT语句的末尾。这是因为对数据行进行排列的操作必须在结果即将返回时执行。
使用HAVING子句时SELECT语句的顺序:
1.SELECT子句->2.FROM子句->3.WHERE子句->4.GROUP BY子句->5.HAVING子句->6.ORDER BY子句

指定升序或降序
ORDER BY列名后加上ASC/DESC关键字。未指定ORDER BY子句中排列顺序时会默认使用升序进行排列。
ASC
Ascendent 上升的
DESC
Descendent  下降的

指定多个排序键
     如果指定了多个排序键,那么会优先使用左侧的键,当该列存在相同值时,会接着参考右侧的键。
Eg:
SELECT shohin_id, shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
ORDER BY hanbai_tanka, shohin_id;

**当使用含有NULL的列作为排序键时,NULL会在结果的开头或末尾汇总显示。

ORDER BY子句中可以使用SELECT子句中定义的别名
    GROUP BY子句中不允许使用别名,为什么ORDER BY中可以呢?这是因为SELECT子句的执行顺序在GROUP BY子句之后,在ORDER BY子句之前。
Eg:
SELECT shohin_id AS id, shohin_mei, hanbai_tanka AS ht, shiire_tanka
FROM Shohin
ORDER BY ht, id;

**ORDER BY子句中可以使用表中的列(无论SELECT子句中是否使用)和聚合函数。
**ORDER BY子句中还可以使用列编号,但是最好不这么用。因为代码阅读起来比较困难,并且该排序功能将来可能会被删除(SQL-92中明确指出)。

Friday, July 1, 2016

数据库学习



数据库的结构
Keypoint:
1.       RDBMS最常见的系统结构是客户端/服务器(C/S类型)。
2.       通过从客户端向服务器端发送SQL语句来实现数据库的读写操作。
3.       关系数据库采用被称为数据库表的二维表来管理数据。
4.       数据库表由表示数据项目的列(字段)和表示一条数据的行(记录)所组成,以记录为单位进行读写。
5.       行和列交汇的方格称为单元格,每个单元格只能输入一个数据。

1.       根据SQL语句内容返回的数据,必须是二维表的形式。
2.       关系数据库以行为单位读写数据。
3.       一个单元格中只能输入一个数据。
4.       SQL根据功能不同分为三类:DDL,DML,DCL,其中使用最多的是DML

SQL的基本书写规则
法则1-5.  SQL语句都要以分号(;)结尾。
法则1-6.  SQL语句不区分大小写。例如,不管写成SELECT还是select。表名和列名也是如此。但是最好还是有一定规范:
关键字大写
表名的首个字大写
其余(列名等)小写
需要注意的是,插入到表中的数据是区分大小写的。
法则1-7.  常数的书写方式是固定的。字符串喝日期常数需要使用单引号()括起来。数字常数则是直接书写即可
法则1-8.  单词需要用半角空格或者换行来间隔。

1-4表的创建
         数据库名称、表名以及列名都要使用半角字符(英文字母、数字、符号)。
1.       创建数据库的语句:
CREATE DATABASE <数据库名称>
EgCREATE DATABASE shop(将数据库命名为shop
2.       创建表的语句:
CREATE TABLE <表名>
(<列名1>  <数据类型> <该列所需约束>,
<列名2>  <数据类型> <该列所需约束>,
<列名3>  <数据类型> <该列所需约束>,
<列名4>  <数据类型> <该列所需约束>,
           
 <该表的约束1>, <该表的约束2>, …)
Eg:
CREATE TABLE Shohin
(
shohin_id
CHAR(4)
NOT NULL

shohin_mei
VARCHAR(100)
NOT NULL

shohin_bunrui
VARCHAR(32)
NOT NULL

hanbai_tanka
INTEGER
,

shiire_tanka
INTEGER
,

torokubi
DATE
,
PRIMARY KEY  (shohin_id));

命名规则
法则1-9.  数据库名称、表名和列名可以使用一下三种字符。
1.       半角英文字母
2.       半角数字
3.       下划线(_

法则1-10.  名称必须以半角英文字母作为开头。
比如不能以数字开头。

法则1-11.  名称不能重复。
商品表中的列名
Shohin表定义的列名
商品编号
shohin_id
商品名称
shohin_mei
商品分类
shohin_bunrui
销售单价
hanbai_tanka
进货单价
shiire_tanka
登记日期
torokubi

数据类型的指定
1.       INTEGER   存整数,但不能存储小数。
2.       CHAR   定长字符串型,可以像CHAR(10) 这样,在括号中指定该列可以存储的字符串的最大长度。超出该长度的部分是无法输入该列的。字符串以定长字符串的形式存储。所谓定长,是指当列中存储的字符串长度达不到最大长度的时候,使用半角空格进行补足。区分大小写。
3.       VARCHAR   可变长字符串型。顾名思义,即使输入的字符数未达最大长度,也不会用半角空格补足。区分大小写。
4.       DATE    日期型,用来指定存储日期(年月日)的列的数据类型。

约束的设置:
约束是除了数据类型之外,对列中存储的数据进行限制或者追加条件的功能。
Shohin有两种。
1.       “shohin_id   CHAR(4)   NOT NULL”NOT NULL是指该列设定了不能输入空白。
2.       “PRIMARY KEY(shohin_id)”   设定为主键表示唯一确定一行数据。



1-5  表的删除与更新
         删除的表是无法恢复的,所以尽量少做这样的操作。
1.       删除表的语句
DROP TABLE <表名>;
Eg: DROP TABLE Shohin;
2.       更新语句(ALTER TABLE
2.1   添加列的语句
ALTER TABLE <表名> ADD COLUMN <列的定义>
Eg: ALTER TABLE Shohin ADD COLUMN shohin_mei_kana VARCHAR(100);
2.2   删除列的语句
ALTER TABLE <表名> DROP COLUMN <列的定义>
Eg: ALTER TABLE Shohin DROP COLUMN shohin_mei_kana VARCHAR(100);
不过有一些特殊的SQLOracleSQL Server中不用写COLUMN。它们一般是
ALTER TABLE <表名> ADD <列名>;
多列的时候 ALTER TABLE <表名> ADD  (<列名>,<列名>,……);
同理, ALTER TABLE <表名> DROP <列名>;

法则1-13 表定义变更之后无法恢复,所以在执行ALTER TABLE语句之前请务必仔细确认。

插入数据
SQL Server PostgreSQL
BEGIN TRANSACTION;
INSERT INTO Shohin VALUES (‘0001’, ‘T恤衫’, ’衣服’, 1000, 500, ‘2009-09-20’);
INSERT INTO Shohin VALUES (‘0002’, ‘打孔器’, ’办公用品’, 500, 320, ‘2009-09-11’);
COMMIT;
DBMS不同,DML语句也略有不同:
MySQL中需要把BEGIN TRANSACTION;  改写成START TRANSACTION;





2-1 SELECT语句
SELECT <列名>,……
  FROM <表名>;
Eg: SELECT shohin_id, shohin_mei, shiire_tanka
FROM Shohin;

查询全部的列,可以用星号(*)。
SELECT *
  FROM <表名>
**不过如果使用星号的话,就无法设定列的显示顺序了。这时就会按照CREATE TABLE 语句的定义对列进行排序。
**SQL语句是可以使用换行符或者半角空格来分隔单词的。不过,插入空行的话不行,会造成执行错误。

为列设定别名
         SQL语句可以使用AS关键字为列设定别名。
SELECT shohin_id AS id,
      shohin_mei AS name,
      shiire_tanka AS tanka
  FROM Shohin;
别名可以使用汉语,使用汉语时需要用双引号(“)括起来。

从结果中删除重复行
SELECT DISTINCT shohin_bunrui
  FROM Shohin;
         在使用DISTINCT时,NULL也被视为一类数据。存在多条NULL数据行时,也会结合为一条NULL 数据(相当于说它还是会被保留显示出来)。
         DISTINCT在多列之间使用的话,则会将多个列的数据进行组合,将组合后的数据重复的结合为一条。
         ** DISTINCT关键字只能用在第一个列名之前。

根据WHERE语句来选择记录
         WHERE语句用来设定一种查询数据的条件。比如“某一列的值和这个字符串相等”或者“某一列的值大于这个数字”等。
SELECT <列名>, ……
FROM <表名>
WHERE <条件表达式>;
Eg:
SELECT shohin_mei, shohin_bunrui
FROM Shohin
WHERE shohin_bunrui = ‘衣服’;
此流程是首先通过WHERE 子句查询出符合指定条件的记录,然后再选取出SELECT语句指定的列(即选出行后,再输出列)。
其中,在输出的时候,也可以不选取作为查询条件的列
Eg:
SELECT shohin_mei
FROM Shohin
WHERE shohin_bunrui = ‘衣服’;

**SQL中子句的书写顺序是固定的,不能随便更改。WHERE子句必须紧跟在FROM之后。

注释的书写方法
有两种:
1.       单行注释:书写在“--”之后,只能写在同一行。
2.       多行注释:书写在“/*”和“*/”之间,可以跨多行。





2-2 算术运算符和比较运算符
算数运算符
         算数运算符就是使用其两边的值进行四则运算或者字符串拼接、数值大小比较等运算,并返回结果的符号。另外,SQL 也可以像平常的运算表达式那样使用括号。不过括号的使用并不仅仅局限于四则运算,它可以用在任何表达式中。
Code:
SELECT shohin_mei, hanbai_tanka, hanbai_tanka*2 AS “hanbai_tanka_x2”
  FROM Shohin
 
需要注意NULL
         所有包含NULL的计算,结果都是NULL。(特别是, 通常情况下,类似5/0这样除数为0的话会引发错误,而NULL/0不会,其结果仍是NULL)。

比较运算符
运算符
含义
=
~相等
<> 
~不相等
>=
大于等于
大于
<=
小于等于
小于

Eg:
SELECT shohin_mei, shohin_bunrui
FROM Shohin
WHERE hanbai_tanka <> 500;


小于某个日期就是在该日期之前的意思。
SELECT shohin_mei, shohin_bunrui, torokubi
FROM Shohin
WHERE torokubi < ‘2009-09-27’;

也可以使用比较运算符对计算结果进行比较。
SELECT shohin_mei, hanbai_tanka, shiire_tanka
FROM Shohin
WHERE hanbai_tanka-shiire_tanka >= 500;

**字符串类型的比较和数字是不一样的,相当于是按照字典顺序进行的排序。
如果输入CHAR 类型的‘2’,‘10’,‘3’,其比较的结果是‘10<2<3’。

**不能对NULL使用比较运算符,如果需要判断则用IS NULL或者 IS NOT NULL
SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka IS NULL;




2-3逻辑运算符
NOT运算符
NOT 的使用范围较”<>”要更广泛一些。它不能单独使用,必须和其他查询条件组合起来使用。可是呢,说实在的,一定不能滥用,语文里面就说过,否定一多就让人难以理解。
SELECT shohin_mei, shohin_bunrui, hanbai_tanka
FROM Shohin
WHERE NOT hanbai_tanka >= 1000;
上面的条件语句等价于WHERE hanbai_tanka < 1000

   AND 运算符和OR 运算符
      和咱平时用的与或是一样意思。
      AND –>两个条件都要满足
      OR –>满足其中一个条件就可以
SELECT shohin_mei, shohin_bunrui, hanbai_tanka
FROM Shohin
WHERE shohin_bunrui=’厨房用具
   AND hanbai_tanka >= 3000;
     **需要注意的是,AND运算优先于OR运算执行。所以多个使用的时候记得使用括号来解决优先级会造成的意外困扰。如果对复杂的逻辑运算感到模糊,也可以建立真值表。

我们把AND运算符称为逻辑积,OR运算符称为逻辑和。
trueà1, falseà0;
P
Q
P AND Q
1
1
1*1
1
1
0
1*0
0
0
1
0*1
0
0
0
0*0
0

P
Q
P OR Q
1
1
1+1
1
1
0
1+0
1
0
1
0+1
1
0
0
0+0
0

   含有NULL的逻辑运算
   NULLSQL中是除真假之外的第三种值——不确定(UNKNOWN)。
   考虑NULL的时候条件判断会变得复杂很多,所以“尽量不使用NULL”,这也是为什么表中时常要设置NOT NULL的约束条件。

 


KEY: 聚合与排序
3-1 对表进行聚合查询
COUNT
计算表中的记录数(行数)
SUM
计算表中数值列的数据平均值
AVG
计算表中数值列的数据平均值
MAX
求出表中任意列中数据的最大值
MIN
求出表中任意列中数据的最小值