跳转至内容

十一级信息学实践(CBSE)/连接与子查询

来自维基教科书,开放书籍,开放世界

SQL 最重要的方面是其关系特性。您可以查询、比较和计算两个具有完全不同结构的不同表。连接和子选择是连接表的两种方法。两种连接表的方法应该给出相同的结果。在大多数 SQL 平台上,自然连接更快。

在下面的例子中,一个学生试图学习印地语中数字的叫法。

CREATE TABLE english (Tag int, Inenglish varchar(255));
CREATE TABLE hindi (Tag int, Inhindi varchar(255));
INSERT INTO english (Tag, Inenglish) VALUES (1, 'One');
INSERT INTO english (Tag, Inenglish) VALUES (2, 'Two');
INSERT INTO english (Tag, Inenglish) VALUES (3, 'Three');
INSERT INTO hindi (Tag, Inhindi) VALUES (2, 'Do');
INSERT INTO hindi (Tag, Inhindi) VALUES (3, 'Teen');
INSERT INTO hindi (Tag, Inhindi) VALUES (4, 'Char');
 从英文中选择 * 从印地语中选择 *
标签英文标签印地语
1 2
2 3 青少年
3 4

笛卡尔积连接

[编辑 | 编辑源代码]

笛卡尔积连接是指将一个表中的每一行与另一个表中的每一行连接起来。

SELECT * FROM english, hindi

它也被称为交叉连接,可以这样写

SELECT * FROM english CROSS JOIN hindi
标签英文标签 印地语
1 2
2 3 青少年
3 4

内部连接

[编辑 | 编辑源代码]
SELECT hindi.Tag, english.Inenglish, hindi.Inhindi
FROM english, hindi
WHERE english.Tag = hindi.Tag
标签 英文 印地语
2
3 青少年

您也可以将相同的查询写成

SELECT hindi.Tag, english.Inenglish, hindi.Inhindi
FROM english INNER JOIN hindi
ON english.Tag = hindi.Tag

使用“using”的自然连接(兼容:MySQL 4+;但在 MySQL 5 中已更改)以下使用“USING”方法的语句将显示相同的结果。

SELECT hindi.tag, hindi.Inhindi, english.Inenglish
FROM hindi NATURAL JOIN english
USING (Tag)

外部连接

[编辑 | 编辑源代码]
标签 英文 标签 印地语
1   
2 2
3 3 青少年
    4

左连接/左外部连接

[编辑 | 编辑源代码]

语法如下

SELECT field1, field2 FROM table1 LEFT JOIN table2 ON field1=field2
SELECT e.Inenglish as English, e.Tag, '--no row--' as Hindi
FROM english AS e LEFT JOIN hindi AS h
ON e.Tag=h.Tag 
WHERE h.Inhindi IS NULL
English  tag   Hindi
One      1     --no row-

右外部连接

[编辑 | 编辑源代码]
SELECT '--no row--' AS English, h.tag, h.Inhindi AS Hindi
FROM english AS e RIGHT JOIN hindi AS h
ON e.Tag=h.Tag
WHERE e.Inenglish IS NULL

英文标签印地语--无行--4 炭

  • 确保您在两个表中具有相同的名称和相同的数据类型。
  • 关键字 LEFT 和 RIGHT 不是绝对的,它们仅在给定语句的上下文中起作用:我们可以颠倒表的顺序并颠倒关键字,结果将相同。
  • 如果没有指定连接类型为内部或外部,则将执行为内部连接。

全外部连接

[编辑 | 编辑源代码]

对于 v5.1,MySQL 不提供 FULL OUTER JOIN。您可以使用一系列联合的 SELECT 语句来模拟它。

多重连接

[编辑 | 编辑源代码]

可以连接两个以上的表

SELECT ... FROM a JOIN (b JOIN c on b.id=c.id) ON a.id=b.id

以下来自 *萨凡纳* 的示例

mysql> SELECT group_type.type_id, group_type.name, COUNT(people_job.job_id) AS count 
       FROM group_type
        JOIN (groups JOIN people_job ON groups.group_id = people_job.group_id) 
        ON group_type.type_id = groups.type
       GROUP BY type_id ORDER BY type_id
+---------+--------------------------------------+-------+
| type_id | name                                 | count |
+---------+--------------------------------------+-------+
|       1 | Official GNU software                |   148 |
|       2 | non-GNU software and documentation   |   268 |
|       3 | www.gnu.org portion                  |     4 |
|       6 | www.gnu.org translation team         |     5 |
+---------+--------------------------------------+-------+
4 rows in set (0.02 sec)

子查询

[编辑 | 编辑源代码]

(兼容:Mysql 4.1 及更高版本...*粗体文字*)

  • SQL 子查询允许您将一个查询的结果用作另一个查询的一部分。
  • 子查询通常是编写语句的自然方式。
  • 允许您将查询分解成片段并组装起来。
  • 允许某些其他方式无法构建的查询。不使用子查询,您必须分两步完成。
  • 子查询始终出现在 WHERE(或 HAVING)子句中。
  • 子查询 SELECT 中只能有一个字段。这意味着子查询只能生成一列数据作为其结果。
  • 不允许使用 ORDER BY;这没有意义。
  • 通常引用子查询中主表列的名称。
  • 这定义了正在运行子查询的主表的当前行。这被称为外部引用。

例如,如果 RepOffice=Offices 表中的 OfficeNbr,列出销售配额超过单个销售人员配额总和的办公室

SELECT City FROM Offices WHERE Target > ???

??? 是销售人员配额的总和,即

SELECT SUM(Quota)
FROM SalesReps 
WHERE RepOffice = OfficeNbr

我们将这些结合起来得到

SELECT City FROM Offices 
WHERE Target > (SELECT SUM(Quota) FROM SalesReps 
WHERE RepOffice = OfficeNbr)

显示所有有订单或信用额度 > 50,000 美元的客户。使用 DISTINCT 词语仅列出客户一次。

SELECT DISTINCT CustNbr 
FROM Customers, Orders 
WHERE CustNbr = Cust AND (CreditLimit>50000 OR Amt>50000);
华夏公益教科书