[SQL]基础SQL

SQL简介

SQL是结构化查询语言(Structure Query Language)的缩写,它是使用关系模型的数据库(RDBMS)应用语言。

SQL历史

在1970年代初,由IBM公司San Jose,California研究实验室的Edgar Frank Codd(又称Ted Codd)发表将数据组成表格的应用原则(Codd's Relational Algebra)。1974年,同一实验室的D.D.Chamberlin和R.F. Boyce对Codd's Relational Algebra在研制关系数据库管理系统System R中,研制出一套规范语言-SEQUEL(Structured English Query Language),并在1976年11月的IBM Journal of R&D上公布新版本的SQL(叫SEQUEL/2)。1980年改名为SQL。
1979年ORACLE公司首先提供商用的SQL,IBM公司在DB2和SQL/DS数据库系统中也实现了SQL。[1]

Ted Codd是绝对的数据库开创者,以relation model获得1981年图灵奖。我们在关系模型中的Boyce-Codd Normal From(介于第三范式和第四范式)也来自于他的名字。

System R在数据库历史上也绝对的重要。特别是看书的时候不断被提起。

SQL标准

1986年10月,美国ANSI采用SQL作为关系数据库管理系统的标准语言(ANSI X3. 135-1986),后为国际标准化组织(ISO)采纳为国际标准。
1989年,美国ANSI采纳在ANSI X3.135-1989报告中定义的关系数据库管理系统的SQL标准语言,称为ANSI SQL 89,该标准替代ANSI X3.135-1986版本。该标准为下列组织所采纳:
国际标准化组织(ISO),为ISO 9075-1989报告“Database Language SQL With Integrity Enhancement”
美国联邦政府,发布在The Federal Information Processing Standard Publication(FIPS PUB)127
当前,所有主要的关系数据库管理系统支持某些形式的SQL,大部分数据库至少遵守ANSI SQL89标准。
ANSI SQL92标准在交叉连接(cross join)和内部连接之上,新增加了外部连接,并支持在FROM子句中写连接表达式。支持集合的并运算、交运算。支持Case (SQL)表达式。支持CHECK约束。创建临时表。支持cursor。
支持事务隔离。[1]

关于此文章

我们这一篇文章采用PostgreSQL的SQL语法。重点我们关注select...from...where这种读操作,分析query (analytical query)。
数据集在 https://hyper-db.de/interface.html 可以直接使用。另外在这个网页不允许进行写操作:insert, update, delete之类的transactional query。当然create tabledrop table也不被允许。

架构 Schema:

schema_de
schema_en

下载:
https://db.in.tum.de/teaching/ws1920/grundlagen/uni_mysql.sql?lang=de

Schma和大部分SQL语句来自Prof. Alfons Kemper, Ph.D.的课件和书。

课件:

书: https://db.in.tum.de/teaching/bookDBMSeinf/?lang=de

基础SQL

  • 搜索所有rang是C4的教授:
select persnr, name
from professoren
where rang = 'C4'
  • 对所有的教授先对rang倒序排序,再对name正序排序:
select persnr, name, rang
from professoren
order by rang desc, name asc
  • 得到professoren的rank的所有可能:
select distinct rang
from professoren
  • 搜索开Maeeutik这个课的教授:
select p.name, v.titel
from professoren p, vorlesungen v
where p.persnr = v.gelesenvon and titel = 'Maeeutik'
  • 列出学生名字和该学生听过的课:
select s.name, v.titel
from studenten s, hoeren h, vorlesungen v
where s.matrnr = h.matrnr and h.vorlnr = v.vorlnr
  • 搜索每个课被多少学生听,考虑没有人听的课,进行倒序排序:
select v.vorlnr, v.titel, count(h.matrnr) as num
from vorlesungen v left outer join hoeren h on v.vorlnr = h.vorlnr
group by v.vorlnr, v.titel
order by num desc 
  • 搜索assistenten的name和professoren的name的并集:
(select name
from assistenten)
union
(select name
from professoren)
  • 搜索没有任何课的教授:
-- correlated sub-query
select p.name
from professoren p
where not exists(
    select *
    from vorlesungen v
    where v.gelesenvon = p.persnr
    )

-- un-correlated sub-query
-- not in: 集合的比较
select p.name
from professoren p
where p.persnr not in (
    select v.gelesenvon
    from vorlesungen v
    )
  • 搜索不上任何课的学生:
-- correlated sub-query
select s.name
from studenten s
where not exists(
    select *
    from hoeren h
    where h.matrnr = s.matrnr
    )

-- un-correlated sub-query
-- not in: 集合的比较
select s.name
from studenten s
where s.matrnr not in (
    select h.matrnr
    from hoeren h
    )
  • 听大于等于3门课学生
select s.matrnr, s.name
from studenten s, hoeren h
where s.matrnr = h.matrnr
group by s.matrnr, s.name
having count(*) >= 3
  • 搜索semester最大的学生:
select s.name
from studenten s
where s.semester >= all (
    select semester
    from studenten
    )
  • 求得studenten的平均semester:
select avg(semester)
from studenten
  • 搜索sws>=4并且作为至少其他两门课以上的vorgaenger:
select v.vorlnr, v.titel
from vorlesungen v, voraussetzen vor
where v.vorlnr = vor.vorgaenger and v.sws >= 4
group by v.vorlnr, v.titel
having count(*) >= 2
  • 搜索每一个教授上的课的SWS的各自总和:
select v.gelesenvon, sum(v.sws)
from vorlesungen v
group by v.gelesenvon
  • 搜索有rank C4的professoren中上课总SWS超过3的professoren:
select v.gelesenvon, p.name, sum(v.sws)
from vorlesungen v, professoren p
where v.gelesenvon = p.persnr and rang = 'C4'
group by v.gelesenvon, p.name
having avg(v.sws) >= 3

这里需要注意一下aggregation operation。
对每一个group都会生成一个tuple。所以对于带有group by子句的SQL语句,select子句里面只能是group by子句提到的属性值和aggregation operation。

  • 比较的syntax sugar(语法糖)
SELECT *
FROM studenten 
WHERE semester >= 1 AND semester <= 4;

SELECT *
FROM studenten 
WHERE semester between 1 and 4;

SELECT *
FROM studenten 
WHERE semester in (1,2,3,4);
  • 字符串比较:
SELECT *
FROM studenten 
WHERE name like 'T%eophrastos';

SELECT DISTINCT s.name
FROM vorlesungen v, hoeren h, studenten s
WHERE s.matrnr = h.matrnr AND h.vorlnr = v.vorlnr AND v.titel LIKE '%thik%';
  • case
SELECT matrnr, 
            (case when note <= 1.5 then 'sehr gut'
               when note <= 2.5 then 'gut'
               when note <= 3.5 then 'befriedigend'
               when note <= 4.0 then 'ausreichend'
               else 'nicht bestanden'
            end)
FROM pruefen;
  • left outer join:
SELECT p.persnr, p.name, f.persnr, f.note, f.matrnr, s.matrnr, s.name
FROM professoren p left outer join pruefen f left outer JOIN studenten s ON f.matrnr = s.matrnr ON p.persnr = f.persnr;
  • right outer join:
SELECT p.persnr, p.name, pf.persnr, pf.note, pf.matrnr, s.matrnr, s.name
FROM professoren p right outer JOIN pruefen pf right outer JOIN studenten s ON pf.matrnr = s.matrnr ON p.persnr = pf.persnr;
  • full outer join:
SELECT p.persnr, p.name, pf.persnr, pf.note, pf.matrnr, s.matrnr, s.name
FROM professoren p full outer JOIN pruefen pf full outer JOIN studenten s ON pf.matrnr = s.matrnr ON p.persnr = pf.persnr;

</br>
</br>

-- precompute look up table
with mtable as (values
( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
( 2, 4, 6, 8, 10, 12, 14, 16, 18, 20),
( 3, 6, 9, 12, 15, 18, 21, 24, 27, 30),
( 4, 8, 12, 16, 20, 24, 28, 32, 36, 40),
( 5, 10, 15, 20, 25, 30, 35, 40, 45, 50),
( 6, 12, 18, 24, 30, 36, 42, 48, 54, 60),
( 7, 14, 21, 28, 35, 42, 49, 56, 63, 70),
( 8, 16, 24, 32, 40, 48, 56, 64, 72, 80),
( 9, 18, 27, 36, 45, 54, 63, 72, 81, 90),
( 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
)
select * from mtable

或者

with mtable_column(a, b, c, d, e, f, g, h, i, k) as (values
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) -- 其实被写成一行
),
mtable_row(x) as (values
(1), (2), (3), (4), (5), (6), (7), (8), (9), (10) -- 其实被写成一列
)
select
a * x,
b * x,
c * x,
d * x,
e * x,
f * x,
g * x,
h * x,
i * x,
k * x
from mtable_column, mtable_row

该文章遵循创作共用版权协议 CC BY-NC 3.0,要求署名、非商业 、保持一致。在满足创作共用版权协议 CC BY-NC 3.0 的基础上可以转载,但请以超链接形式注明出处。文章仅代表作者的知识和看法,如有不同观点,可以回复并讨论。


  1. SQL 维基百科. https://zh.wikipedia.org/wiki/SQL

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容