如何创建具有多个聚合函数count和sum的视图?

时间:2012-05-05 21:50:42

标签: sql oracle

我正在尝试为我的oracle表单创建摘要。此摘要将存储每个部门的员工数量。记录存储在一个表中,其中不同的列表示部门名称(例如小时,它......) 代码:

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,这是一个没有商业化的学校项目。

2 个答案:

答案 0 :(得分: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 KEYFOREIGN KEY的许多其他内容。

  • 您无法切换创建这些表的顺序。换句话说,您不能先创建Person表,然后再创建Department表。原因是Person表正在创建一个引用Department表的约束。如果先创建Person表,则会收到错误Failed: ORA-00942: table or view does not exist

  • 您还可以将dept_noperson_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中具有单行的虚拟表。 Read here in this SO answer about dual.

脚本

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是非聚合列。 SUMMAXMIN是一些集合函数。

  • 最后,我们应用 ORDER BY 子句按 dept_no 列对输出进行排序。

演示

Click here to view the demo in SQL Fiddle.

答案 1 :(得分: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;