从属表
现在让我们的查询复杂一点。让我们向我们的数据库添加一个新的任务表,其中包含我们员工的任务。让我们看看它包含哪些条目:
SELECT * FROM task
这样请求的结果:
ID | emploee_id | 姓名 | 最后期限 |
---|---|---|---|
1个 | 1个 | 修复一个前端bug | 2022-06-01 |
2个 | 2个 | 修复后端的一个bug | 2022-06-15 |
3个 | 5个 | 买咖啡 | 2022-07-01 |
4个 | 5个 | 买咖啡 | 2022-08-01 |
5个 | 5个 | 会买咖啡 | 2022-09-01 |
6个 | (无效的) | 打扫办公室 | (无效的) |
7 | 4个 | 享受生活 | (无效的) |
8个 | 6个 | 享受生活 | (无效的) |
该表只有 4 列:
- id — 唯一的任务编号(和表中的行);
- employee_id — 分配任务的员工表中员工的 ID;
- 名称― 任务的名称和描述;
- deadline - 任务必须完成的时间。
注意一些细微差别。任务 N6 没有 employee_id,我们没有清洁工。任务在那里,但执行者不在。它发生了。
此外,任务 6-9 没有设定的截止日期。当必须定期和连续地完成一项任务时,就会发生这种情况。比如办公室每天都要打扫卫生,但你也需要每天享受生活:)
如果一个表使用另一个表的 ID,那么这样的表称为dependent。
查询多个表
这里我们在任务表中看到有两个任务“享受生活”。我们怎么知道这些幸运儿是谁?
为此,在 SQL 中,您可以同时对两个表执行查询。一般来说,在SQL中,可以同时查询任意多张表。这种请求的一般格式是:
SELECT columns
FROM Table 1, table 2, tableN
重要的!如果您同时对多个表编写查询,那么您将得到所谓的表行的笛卡尔积。第一个表中的每一行将粘附到第二个表中的每一行,依此类推。
也就是说,如果第一个表中有 5 行,第二个表中有 10 行,那么总共有 50 行。在 Java 中,这个查询看起来像这样:
for (String row1 : table1)
{
for (String row2 : table2)
{
System.out.println(row1 + row2);
}
}
让我们一次将查询写入两个表,看看会发生什么:
SELECT * FROM employee, task
这个查询的结果是:
ID | 姓名 | 职业 | 薪水 | 年龄 | ID | 雇员 | _ID | 姓名 | 最后期限 |
---|---|---|---|---|---|---|---|---|---|
1个 | 伊万诺夫伊万 | 程序员 | 100000 | 25 | 1个 | 1个 | 修复一个前端bug | 2022-06-01 | |
2个 | 彼得罗夫彼得 | 程序员 | 80000 | 23 | 1个 | 1个 | 修复一个前端bug | 2022-06-01 | |
3个 | 伊万诺夫谢尔盖 | 测试员 | 40000 | 三十 | 1个 | 1个 | 修复一个前端bug | 2022-06-01 | |
4个 | 拉比诺维奇·莫伊沙 | 导演 | 200000 | 35 | 1个 | 1个 | 修复一个前端bug | 2022-06-01 | |
5个 | 基连科阿纳斯塔西娅 | 办公室主管 | 40000 | 25 | 1个 | 1个 | 修复一个前端bug | 2022-06-01 | |
6个 | 瓦斯卡 | 猫 | 1000 | 3个 | 1个 | 1个 | 修复一个前端bug | 2022-06-01 | |
1个 | 伊万诺夫伊万 | 程序员 | 100000 | 25 | 2个 | 2个 | 修复后端的一个bug | 2022-06-15 | |
2个 | 彼得罗夫彼得 | 程序员 | 80000 | 23 | 2个 | 2个 | 修复后端的一个bug | 2022-06-15 | |
3个 | 伊万诺夫谢尔盖 | 测试员 | 40000 | 三十 | 2个 | 2个 | 修复后端的一个bug | 2022-06-15 | |
4个 | 拉比诺维奇·莫伊沙 | 导演 | 200000 | 35 | 2个 | 2个 | 修复后端的一个bug | 2022-06-15 | |
5个 | 基连科阿纳斯塔西娅 | 办公室主管 | 40000 | 25 | 2个 | 2个 | 修复后端的一个bug | 2022-06-15 |
我们总共有 48 行结果,但这里我只给出了 11 行。否则,空间就不够了。
注意三件事:
- 具有相同名称的列:id。这是employee表中的 id和task表中的 id 。
- 每个表的行都是重复的。在左列中,ID 6 之后又是 ID = 1。
- 我们有无意义的行,例如,id(来自 employee 表)为 6,而在同一行中,employee_id 为 1。
删除无意义的行
结果表中的行太多 ,这是employee和task两个表的所有行的笛卡尔积。
从逻辑上讲,如果行 employee_id 为 3,那么它应该只保留 employee 表中 id 为 3 的行。让我们尝试用 WHERE 来解决这个误解。
让我们写一个这样的查询:
SELECT * FROM employee, task
WHERE emploee.id = task.emploee_id
这个查询的结果是:
ID | 姓名 | 职业 | 薪水 | 年龄 | ID | emploee_id | 姓名 | 最后期限 |
---|---|---|---|---|---|---|---|---|
1个 | 伊万诺夫伊万 | 程序员 | 100000 | 25 | 1个 | 1个 | 修复一个前端bug | 2022-06-01 |
2个 | 彼得罗夫彼得 | 程序员 | 80000 | 23 | 2个 | 2个 | 修复后端的一个bug | 2022-06-15 |
4个 | 拉比诺维奇·莫伊沙 | 导演 | 200000 | 35 | 7 | 4个 | 享受生活 | (无效的) |
5个 | 基连科阿纳斯塔西娅 | 办公室主管 | 40000 | 25 | 3个 | 5个 | 买咖啡 | 2022-07-01 |
5个 | 基连科阿纳斯塔西娅 | 办公室主管 | 40000 | 25 | 4个 | 5个 | 买咖啡 | 2022-08-01 |
5个 | 基连科阿纳斯塔西娅 | 办公室主管 | 40000 | 25 | 5个 | 5个 | 会买咖啡 | 2022-09-01 |
6个 | 瓦斯卡 | 猫 | 1000 | 3个 | 8个 | 6个 | 享受生活 | (无效的) |
好消息是无意义的行已经消失:第一列的 id 始终等于 employee_id。
坏消息是没有分配给任何人的任务,例如打扫办公室,都没有了。他们的 employee_id 是 NULL,所以他们在 WHERE 完成后被丢弃。