由于这是一项家庭作业,我想就如何以适当的方式设计表格提供一些意见。只是我的两分钱。
设计建议
我会建议你改变表设计。您的所有表基本上都包含相同的数据:
与其拥有多个表,不如按照这一思路设计数据库,只包含两个表。
Department
----------
dept_no INTEGER
dept_name VARCHAR(30)
Person
------
person_no INTEGER
person_name VARCHAR(30)
dept_no INTEGER
创建带约束的表
您应该设计具有适当约束的表。这里有几点需要注意。
顾名思义,该约束PRIMARY KEY
将在表上创建一个主键以保持数据的唯一性,这样您就不会得到多个具有相同值的 id。
约束FOREIGN KEY
是在表 Department 和 Person 之间创建关系。
对于此示例,这些键可能不是必需的,但在现实世界的应用程序中,使用外键约束定义适当的关系始终是最佳实践。您可以在网络上搜索许多其他PRIMARY KEY
内容FOREIGN KEY
。
您无法切换这些表的创建顺序。换句话说,您不能先创建 Person 表,然后再创建 Department 表。原因是 Person 表正在创建一个引用 Department 表的约束。如果您先创建 Person 表,您将收到错误Failed: ORA-00942: table or view does not exist
。
您还可以将dept_no
andperson_no
设为自动递增的数字,这样您就不必手动插入这些数字。我使用 SQL Server。所以,我不太熟悉 Oracle 语法来创建一个自动递增数字的列。搜索 Oracle 的序列号,你可能会找到一些东西。
脚本:
CREATE TABLE Department
(
dept_no INTEGER
, dept_name VARCHAR(30)
, CONSTRAINT pk_department PRIMARY KEY (dept_no)
);
CREATE TABLE Person
(
person_no INTEGER
, person_name VARCHAR(30)
, dept_no INTEGER
, CONSTRAINT pk_person PRIMARY KEY (person_no)
, CONSTRAINT fk_person_dept FOREIGN KEY (dept_no)
REFERENCES Department (dept_no)
);
填充表格
下面给出的脚本首先填充 Department 表,然后填充 Person 表。
它实际上是同时向表中插入多个值,而不是为每一行调用 INSERT INTO。
dual是 Oracle 中的单行虚拟表。在这个关于双重的 SO 答案中阅读此处。
脚本:
INSERT ALL
INTO Department (dept_no, dept_name) VALUES (1, 'Cleaner')
INTO Department (dept_no, dept_name) VALUES (2, 'Driver')
INTO Department (dept_no, dept_name) VALUES (3, 'Mechanic')
SELECT * FROM dual;
INSERT ALL
INTO Person (person_no, person_name, dept_no) VALUES (1, 'Cleaner 1', 1)
INTO Person (person_no, person_name, dept_no) VALUES (2, 'Cleaner 2', 1)
INTO Person (person_no, person_name, dept_no) VALUES (3, 'Cleaner 3', 1)
INTO Person (person_no, person_name, dept_no) VALUES (4, 'Cleaner 4', 1)
INTO Person (person_no, person_name, dept_no) VALUES (5, 'Driver 1', 2)
INTO Person (person_no, person_name, dept_no) VALUES (6, 'Driver 2', 2)
INTO Person (person_no, person_name, dept_no) VALUES (7, 'Driver 3', 2)
INTO Person (person_no, person_name, dept_no) VALUES (8, 'Mechanic 1', 3)
INTO Person (person_no, person_name, dept_no) VALUES (9, 'Mechanic 2', 3)
INTO Person (person_no, person_name, dept_no) VALUES (10, 'Mechanic 3', 3)
INTO Person (person_no, person_name, dept_no) VALUES (11, 'Mechanic 4', 3)
INTO Person (person_no, person_name, dept_no) VALUES (12, 'Mechanic 5', 3)
INTO Person (person_no, person_name, dept_no) VALUES (13, 'Mechanic 6', 3)
SELECT * FROM dual;
如何让我的数据按部门分组?
简单选择:
SELECT dept_no
, dept_name
FROM Department;
输出:
DEPT_NO DEPT_NAME
------- ---------
1 Cleaner
2 Driver
3 Mechanic
- 所以,你可能会问‘我怎样才能得到这些信息?'。嗯,该信息在表 Person 中。因此,我们需要连接两个表以找到所需的数据。我们将使用
INNER JOIN
在一个公共字段上连接两个表。在这种情况下,两个表中的公共字段是dept_no。
将为您提供所需输出的查询
脚本:
SELECT d.dept_no
, d.dept_name
, COUNT(p.person_no) AS No_of_employees
FROM Department d
INNER JOIN Person p
ON p.dept_no = d.dept_no
GROUP BY d.dept_no
, d.dept_name
ORDER BY d.dept_no;
输出:
DEPT_NO DEPT_NAME NO_OF_EMPLOYEES
------- --------- ---------------
1 Cleaner 4
2 Driver 3
3 Mechanic 6
解释
该查询使用了很多东西,例如 INNER JOIN、GROUP BY、COUNT 和 ORDER BY。让我们来看看其中的每一个。
INNER JOIN基于公共字段连接表,在本例中为 dept_no。
COUNT函数将允许查询按部门编号和部门名称对所有员工计数进行分组。
COUNT
是一个聚合函数。当您对非聚合列使用聚合函数时,您需要使用 GROUP BY 子句。这里的 dept_no 和 dept_name 是非聚合列。SUM
, MAX
. MIN
是一些聚合函数。
最后,我们应用ORDER BY子句按dept_no列对输出进行排序。
演示
单击此处查看 SQL Fiddle 中的演示。