如果你想重用z,您有两种选择。要么重复表达式:
SELECT A.x + A.y AS z
FROM A
WHERE (A.x + A.y) = 10
或者你使用派生表、公用表表达式或视图来避免代码重复。请参阅示例进一步的分析:
3、在语法和逻辑顺序里,UNION都是放在ORDER BY之前,很多人认为每个UNION子查询都可以进行排序,但根据SQL标准和大多数的SQL方言,并不是真的可行。虽然一些方言允许子查询或派生表排序,但却不能保证这种顺序能在UNION操作后保留。
需要注意的是,并不是所有的数据库都以相同的形式实现,例如规则2并不完全适用于MySQL,PostgreSQL,和SQLite上
从中我们学到了什么呢?
要时刻记住SQL语句的语法顺序和逻辑顺序来避免常见的错误。如果你能明白这其中的区别,就能明确知道为什么有些可以执行有些则不能。
如果能设计一种在语法顺序上实际又体现了逻辑顺序的语言就更好了,因为它是在微软的LINQ上实现的。
3、SQL是关于数据表引用的
因为语法顺序和逻辑顺序的差异,大多数初学者可能会误认为SQL中列的值是第一重要的。其实并非如此,最重要的是数据表引用。
该SQL标准定义了FROM语句,如下:
<from clause> ::= FROM <table reference> [ { <comma> <table reference> }... ]
ROM语句的"output"是所有表引用的结合程度组合表引用。让我们慢慢地消化这些。
FROM a, b
上述产生一个a+b度的组合表引用,如果a有3列和b有5列,那么"输出表"将有8(3+5)列。
包含在这个组合表引用的记录是交叉乘积/笛卡儿积的axb。换句话说,每一条a记录都会与每一条b记录相对应。如果a有3个记录和b有5条记录,然后上面的组合表引用将产生15条记录(3×5)。
在WHERE语句筛选后,GROUP BY语句中"output"是"fed"/"piped",它已转成新的"output",我们会稍后再去处理。
如果我们从关系代数/集合论的角度来看待这些东西,一个SQL表是一个关系或一组元素组合。每个SQL语句将改变一个或几个关系,来产生新的关系。
从中我们学到了什么呢?
一直从数据表引用角度去思考,有助于理解数据怎样通过你的sql语句流水作业的
4、SQL数据表引用可以相当强大
表引用是相当强大的东西。举个简单的例子,JOIN关键字其实不是SELECT语句的一部分,但却是"special"表引用的一部分。连接表,在SQL标准中有定义(简化的):
<table reference> ::=
<table name>
| <derived table>
| <joined table>
如果我们又拿之前的例子来分析:
FROM a, b
a可以作为一个连接表,如:
a1 JOIN a2 ON a1.id = a2.id
这扩展到前一个表达式,我们会得到:
FROM a1 JOIN a2 ON a1.id = a2.id, b
虽然结合了数据表引用语法与连接表语法的逗号分隔表让人很无语,但你肯定还会这样做的。结果,结合数据表引用将有a1+a2+b度。
派生表甚至比连接表更强大,我们接下来将会说到。
从中我们学到了什么呢?
要时时刻刻考虑表引用,重要的是这不仅让你理解数据怎样通过你的sql语句流水作业的,它还将帮助你了解复杂表引用是如何构造的。
而且,重要的是,了解JOIN是构造连接表的关键字。不是的SELECT语句的一部分。某些数据库允许JOIN在插入、更新、删除中使用。
5、应使用SQL JOIN的表,而不是以逗号分隔表
前面,我们已经看到这语句:
FROM a, b
高级SQL开发人员可能会告诉你,最好不要使用逗号分隔的列表,并且一直完整的表达你的JOINs。这将有助于改进你的SQL语句的可读性从而防止错误出现。
一个非常常见的错误是忘记某处连接谓词。思考以下内容:
FROM a, b, c, d, e, f, g, h
WHERE a.a1 = b.bx
AND a.a2 = c.c1
AND d.d1 = b.bc
-- etc...
使用join来查询表的语法
更安全,你可以把连接谓词与连接表放一起,从而防止错误。
更富于表现力,你可以区分外部连接,内部连接,等等。??
从中我们学到了什么呢?
使用JOIN,并且永远不在FROM语句中使用逗号分隔表引用。
6、SQL的不同类型的连接操作
连接操作基本上有五种
EQUI JOIN
SEMI JOIN
ANTI JOIN
CROSS JOIN
DIVISION
这些术语通常用于关系代数。对上述概念,如果他们存在,SQL会使用不同的术语。让我们仔细看看:
EQUI JOIN(同等连接)
这是最常见的JOIN操作。它有两个子操作:
INNER JOIN(或者只是JOIN)
OUTER JOIN(可以再次拆分为LEFT, RIGHT,FULL OUTER JOIN)
例子是其中的区别最好的解释:
-- This table reference contains authors and their books. -- There is one record for each book and its author. -- authors without books are NOT included author JOIN book ON author.id = book.author_id -- This table reference contains authors and their books -- There is one record for each book and its author. -- ... OR there is an "empty" record for authors without books -- ("empty" meaning that all book columns are NULL) author LEFT OUTER JOIN book ON author.id = book.author_id |
SEMI JOIN(半连接)
这种关系的概念在SQL中用两种方式表达:使用IN谓词或使用EXISTS谓语。"Semi"是指在拉丁语中的"half"。这种类型的连接用于连接只有"half"的表引用。再次考虑上述加入的作者和书。让我们想象,我们想要作者/书的组合,但只是那些作者实际上也有书。然后我们可以这样写:
-- Using IN
FROM author
WHERE author.id IN (SELECT book.author_id FROM book)
-- Using EXISTS
FROM author
WHERE EXISTS (SELECT 1 FROM book WHERE book.author_id = author.id)
虽然不能肯定你到底是更加喜欢IN还是EXISTS,而且也没有规则说明,但可以这样说:
IN往往比EXISTS更具可读性
EXISTS往往比IN更富表现力(如它更容易表达复杂的半连接)
一般情况下性能上没有太大的差异,但,在某些数据库可能会有巨大的性能差异。
因为INNER JOIN有可能只产生有书的作者,因为很多初学者可能认为他们可以使用DISTINCT删除重复项。他们认为他们可以表达一个像这样的半联接:
-- Find only those authors who also have books
SELECT DISTINCT first_name, last_name
FROM author
这是非常不好的做法,原因有二:
它非常慢,因为该数据库有很多数据加载到内存中,只是要再删除重复项。
它不完全正确,即使在这个简单的示例中它产生了正确的结果。但是,一旦你JOIN更多的表引用,,你将很难从你的结果中正确删除重复项。
更多的关于DISTINCT滥用的问题,可以访问这里的博客。
ANTI JOIN(反连接)
这个关系的概念跟半连接刚好相反。您可以简单地通过将 NOT 关键字添加到IN 或 EXISTS中生成它。在下例中,我们选择那些没有任何书籍的作者:
-- Using IN
FROM author
WHERE author.id NOT IN (SELECT book.author_id FROM book)
-- Using EXISTS
FROM author
WHERE NOT EXISTS (SELECT 1 FROM book WHERE book.author_id = author.id)
同样的规则对性能、可读性、表现力都适用。然而,当使用NOT IN时对NULLs会有一个小警告,这个问题有点超出本教程范围。
CROSS JOIN(交叉连接)
结合第一个表中的内容和第二个表中的内容,引用两个join表交叉生成一个新的东西。我们之前已经看到,这可以在FROM语句中通过逗号分隔表引用来实现。在你确实需要的情况下,可以在SQL语句中明确地写一个CROSS JOIN。
-- Combine every author with every book
author CROSS JOIN book
DIVISION(除法)
关系分割就是一只真正的由自己亲自喂养的野兽。简而言之,如果JOIN是乘法,那么除法就是JOIN的反义词。在SQL中,除法关系难以表达清楚。由于这是一个初学者的教程,解释这个问题超出了我们的教程范围。当然如果你求知欲爆棚,那么就看这里,这里还有这里。
从中我们学到了什么呢?
让我们把前面讲到的内容再次牢记于心。SQL是表引用。连接表是相当复杂的表引用。但关系表述和SQL表述还是有点区别的,并不是所有的关系连接操作都是正规的SQL连接操作。对关系理论有一点实践与认识,你就可以选择JOIN正确的关系类型并能将其转化为正确的SQL。