1

我正在尝试为我的 oracle 表单创建摘要。该摘要将存储每个部门的员工人数。记录存储在一个表中,该表将是指示部门名称的不同列(例如 hr,it ...)代码:

create table cleaners
(
ceno INTEGER,
cname VARCHAR(5)
);

create table drivers
(
eno INTEGER,
dname VARCHAR(5)
);

create table mechanics
(
eno INTEGER,
mname VARCHAR(5)
);

INSERT INTO cleaners VALUES ('1','3');
INSERT INTO cleaners VALUES ('2','3');
INSERT INTO cleaners VALUES ('3','3');
INSERT INTO cleaners VALUES ('4','2');
INSERT INTO cleaners VALUES ('5','2');

INSERT INTO drivers VALUES ('5','3');
INSERT INTO drivers VALUES ('4','3');
INSERT INTO drivers VALUES ('3','3');
INSERT INTO drivers VALUES ('2','2');
INSERT INTO drivers VALUES ('1','2');

INSERT INTO mechanics VALUES ('5','3');
INSERT INTO mechanics VALUES ('4','3');
INSERT INTO mechanics VALUES ('3','3');
INSERT INTO mechanics VALUES ('2','2');
INSERT INTO mechanics VALUES ('1','2');


create view summary as select
count(cleaners.eno) as numberofcleaners,
count(drivers.eno) as numberofdrivers,
count(mechanics.eno) as numberofmechanics,
from  cleaners, drivers, mechanics;

所以我的目标是让每个部门的所有数字都有一行。但是查询返回相乘结果。应该怎么做?我正在使用Oracle6i,这是一个没有商业用途的学校项目。

4

2 回答 2

11

由于这是一项家庭作业,我想就如何以适当的方式设计表格提供一些意见。只是我的两分钱。

设计建议

我会建议你改变表设计。您的所有表基本上都包含相同的数据:

  • 一个号码
  • 姓名

与其拥有多个表,不如按照这一思路设计数据库,只包含两个表。

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_noandperson_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 中的演示。

于 2012-05-05T22:40:24.037 回答
1

您正在查询中进行交叉连接。试试这个:

create view summary 
    as 
    select 
    (select count(cleaners.eno) from cleaners) as numberofcleaners, 
    (select count(drivers.eno) from drivers ) as numberofdrivers, 
    (select count(mechanics.eno) from mechanics) as numberofmechanics
from dual;
于 2012-05-05T21:58:53.373 回答