SQL基础

select food from diet where species='orange';

一句话就能将表diet中的’orange’类的food全部选取出来,也是很神奇的!

查询操作的实现

那么SQL的查询(query)操作是如何实现的呢?

下图给出了很好的解释:

自己写的SQL语句通过网络访问数据库服务器,服务器根据这一指令进行直接查询,结果形成一个表作为返回值。也就是说,SQL语句也只不过是间接查询的途径罢了。

唯一性(uniqueness)

表中的每一个条目都是唯一的,那么如何区分呢?数据库中可以使用id进行区分不同的条目。如果每个条目是一个人的话,那么id就是人的身份证,它是区分人是否不同的权威标准。

Join Table

表animals

name species birthday
Max gorilla 2001-04-13
Max moose 2012-02-22
Sue gorilla 1998-06-12

表diet

name food
llama plants
brown bear fish
brown bear meat
select animals.name,animals.species,diet.food from animals join diet on animals.species=diet.species where food ='fish';

通常由on引导join的条件,也就是将两个表animals和diet关联起来的语句,这里要求的是animals.species 与diet.species相同。这条语句的意思就是查询吃鱼的动物的名字,种类,还有习惯的食物。

SQL中的数据类型

字符串类 数值类型
char(n) 表示 有n 个字符的字符串 integer 整数
varchar(n) 表示 <=n个字符的字符串 real 实数
text 表示任意长度的字符串 double precision 双精度 15位小数
date 日期
time 一天的时间
timestamp 时间戳 既有日期又有时间

比较运算

select .... from table where statements;

statements表示的是过滤条件(row restriction)
这时写这些条件语句的时候边涉及到了比较运算。

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

很简单跟编程语言一样。

常用的keywords

max 函数

select max(name) from animals;

max函数返回最大值,对字符串而言,大小的比较是首先比较头字母的大小。‘a’->’z’从大到小。如果首字母相同,依次比较下一位字母,直到比较出大小,”空字符最小。

select * from animals limit 10;

limit value表示显示前value个条目。

select name from animals where species='orangutan' order by birthdate;

order by col 表示依据col列的值进行升序排序。

select name from animals where species='orangutan' order by birthdate desc;

order by col desc 表示按col列的值降序排列。

select name, birthdate from animals order by name limit 10 offset 20;

offset value 表示偏移值,这个sql语句的含义就是:按name排序得到第位20-30个含有name,birthdate的条目。

select species,min(birthdate) from animals gruop by species;

group by col 表示按col列的值进行聚类,所有col列的值相同的条目算一类。
本sql语句的含义是:得到animals的种类以及每个种类中最小的生日值(年龄最大的)。

select name,count(*) as num from animals gruop by name order by num desc limit 5;

count()函数统计数量
统计animals中的重名动物,并按重名的数量降序排列,得到重名数最多的前五个名字,及其数量。

插入新的行到表中

insert into tablename values(42,’staff’);
if the new values aren’t in the same order as the table’s columns:
insert into tablename(col2,col1) values(‘staff’,42);

比如在animals中插入一行2014-11-11日出生的叫wibble的oppssum类动物:
insert into animals values(‘wibble’,’oppssum’,’2014-11-11’);

Join the Table (simple join)

join 操作往往能被where替代:
比如:
假设T,S是两个表
1. select T.thing , S.stuff from T join S on T.target = S.match;
T.target 与 S.match 就像是桥梁将表T与表S连接起来了。
2. select T.thing , S.stuff from T, S where T.target = S.match;
语句1与语句2可以达到同样的效果
再举个例子:
select name from animals,diet where animals.species = diet.species and diet.food=’fish’;

select animals.name from animals join diet on animals.species = diet.species where diet.food=’fish’;

表示得到吃鱼的动物的名字。

练习时间

question1:which species does the zoo have only one of?

select species,count(*) as num from animals group by species where num=1;

好吧,上面的语句是显而易见的答案,但是如果你这么认为的话,你就错了!
因为 where引导的过滤条件在count开始之前就进行过滤了,但是过滤的时候还没有num产生,这时找不到num必然报错。
用英文说一遍就是:the value of num comes from count and group by.
But where always runs before aggregations.

通过对上面错误答案的微小改动就能得到question1的正确答案。
答案是:

select species,count(*) as num from animals group by species having num=1;

那么having与where的区别是?
where is a restriction on the source tables.
having is a restriction on the result after aggregation.
也就是where引导的条件表达式中的变量必须是源表(source table)中的。

question2:Find the one food the is eaten by only one animal.
answer1:

select food,count(*) as num from animals join diet on animals.species = diet group by food having num=1;

answer2:

select food,count(animals.name) as num from diet,animals where nimals.species = diet group by food having num=1;

Normalized Design

in a normalized database, the relationships among the tables match the relationships that are really there among the data.

Normalized Design
1.Every row has the same number of columns.
2.There is a unique key, and everything in a row says something about the key.
3.Facts that didn’t relate to the key belong in differnt tables.
4.Tables shouldn’t imply relationship that don’t exist.

Greate Table and Types

创建 table 的方法是:
create table tablename(
column1 type [constrains],
column2 type [constains],
…,
…,
[row constrains]);
some systems support abbreviations for long type names.
for example,
timestamptz(PostgreSQL only) = timestamp with time zone (SQL standard type name)

In generally, user facing code doesn’t usually create new tables.
日常生活中,我们一般只是在已有数据库的情况下,对数据库的表进行增删改查操作,并不会直接接触到创建数据库中的表的操作。

Creating and Dropping

Create database name[options];
drop database name[options];
drop table name[options];

在psql中具体进行的就是如下操作:
1.打开terminal:$psql
2.psql=> create database fishies;
3.psql=> \c fishies
4.psql=> create table fish(name text,id serial);
5.psql=> insert into fish values(‘papapa’,1);

Declaring Primary Keys

primary key: a column or columns that uniquely identify what each row in a table is about.
for example,
psql=> create table students(
id serial primary key,
name text,
birthdate date);
有时,也有两个key同时组成primary key.
比如,
psql=> create table post_places(
postal_code text,
country text,
name text,
primary key (post_code,country));
一旦primarykey确定了,当我们输入数据时,如果我们输入的数据中有两个item的primary key 相同,数据库会throws error。

Declaring Relationships

psql=> create table sales(
sku text references products,
sale_date date,
count integer);
products 是一个表
psql=> create table sales(
sku text references products(sku),
sale_date date,
count integer );
products(sku)是一个列
references provides referential integrity-columns that are supporsed to refer to each other are guaranteed to do so.

Foreign Keys

A foreign key is a column or set of columns in one table that uniquely identifies rows in another table.
用法举例
create table students(id serial primary key, name text);
create table courses(id text primary key,name text);
create table grades(student integer references student (id),course text references courses (id), garde text);

下面三个表中哪些列是primary key,哪些列是foreign key?
表users

username fullname
PrinceUtenu TenjoUtenu
AvachnidGrip ViskaSerket
DavFalken DogFootal

表posts:

content author id
Hello! AvachnidGrip 1
I miss u! DavFalken 2

表votes:

post_id voter vote
2 DavFalken -1
1 AvachnidGrip 1

表1中,username是作为primary key的。
表2中,id 作为primary key,author作为foreign key 并参考表1的primary key: username
表3中,post_id 作为foreign key并参考表2的primary key:id;voter作为foreign key参考表1的primary key: username.

self joins

table residences

id building room
413001 crosby 10
116128 dolliver 7
881256 crosby 10
create table residences(id integer references students, building text references buildings(naem), room text);

question:find roommate.

select a.id,b.id from residences as a, residences as b where a.building=b.building and a.room = b.room and a.id<b.id order by a.building, a.room;

left join

**A regular(inner) join returns only those rows where the two tables have entries matching the join condition.
A left join returns all those rows plus the row where the left table has an entry but the right table does not **

create table programs(name text,filename text);
create table bugs(filename text,description text,id serial primary key);

question: count the number of bugs of each program.

select programs.name,count(bugs.id) as num from programs left join bugs on programs.name = bugs.filename group by programs.name order by num;

Subqueries

select avg(bigscore) from (select max(score) as bigscore from mooseball group by team ) as maxer;

the principle is one query, not two!

select name from players,(select avg(weight) as av from players) where weight < av;

or

select name,weight from players,(select avg(weight) as av from players) as subq where weight < av;

Views

A view is a select query stored in the database in a way that lets you use it like a table.

create view viewname as select ......;
create view course_size as select course_id,count(*) as num from enrollment group by course_id;

use view

select * from viewname where ....;

delte view

drop view view_name;