1

オラクルフォームの概要を作成しようとしています。この要約には、各部門の従業員数が格納されます。レコードは、部門の名前 (例: hr、it ...) コードを示す別の列になる 1 つのテーブルに格納されません。

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;

したがって、私の目的は、各部門のすべての番号を含む 1 つの行を作成することです。ただし、クエリは乗算された結果を返しています。それはどのように行われるべきですか?私は Oracle6i を使用しています。これは学校のプロジェクトであり、営利目的ではありません。

4

2 に答える 2

11

これは宿題なので、適切な方法で表を設計する方法について意見を述べたいと思います。ちょうど私の2セント。

デザイン提案

テーブルのデザインを変更することをお勧めします。すべてのテーブルには、基本的に同じデータが含まれています。

  • 名前

複数のテーブルを持つ代わりに、2 つのテーブルのみを含むように、この方針に沿ってデータベースを設計する必要があります。

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 KEYWeb 上で検索できるものは他にもたくさんありますFOREIGN KEY

  • これらのテーブルが作成される順序を切り替えることはできません。つまり、最初に Person テーブルを作成してから Department テーブルを作成することはできません。その理由は、Person テーブルが Department テーブルを参照する制約を作成しているためです。最初に Person テーブルを作成すると、エラーが発生しますFailed: ORA-00942: table or view does not exist

  • dept_noとを自動インクリメントする数値にすることもできるperson_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 は非集計列です。SUMMAXMIN集計関数の一部です。

  • 最後に、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 に答える