Моделирование. Отдел и сотрудник

Запросы SQL по схеме БД

Логическая модель

Логическая модель

Физическая модель

Физическая модель

Создадим необходимые объекты (таблицы, ограничения, индексы):

CREATE TABLE "DEPARTMENT" 
("DEPARTMENT_ID" NUMERIC(11),
 "DEPARTMENT_NAME" VARCHAR2(256)
) TABLESPACE MIRAVILD_DATA;
 
COMMENT ON COLUMN "DEPARTMENT"."DEPARTMENT_ID" IS 'Идентификатор отдела';
COMMENT ON COLUMN "DEPARTMENT"."DEPARTMENT_NAME" IS 'Наименование отдела';
COMMENT ON TABLE "DEPARTMENT" IS 'Отдел';

CREATE UNIQUE INDEX "U_IDX_DEPARTMENT" ON "DEPARTMENT" ("DEPARTMENT_ID") TABLESPACE MIRAVILD_INDEX;

ALTER TABLE "DEPARTMENT" ADD CONSTRAINT "PK_DEPARTMENT" PRIMARY KEY ("DEPARTMENT_ID") 
USING INDEX "U_IDX_DEPARTMENT" ENABLE VALIDATE;
  
ALTER TABLE "DEPARTMENT" MODIFY ("DEPARTMENT_NAME" CONSTRAINT NN_DEPARTMENT_NAME NOT NULL ENABLE);
/

CREATE TABLE "EMPLOYEE" 
("EMPLOYEE_ID" NUMERIC(11),
 "DEPARTMENT_ID" NUMERIC(11),
 "EMPLOYEE_SURNAME" VARCHAR2(256),
 "EMPLOYEE_SALARY" NUMERIC(18, 2)
) TABLESPACE MIRAVILD_DATA;
 
COMMENT ON COLUMN "EMPLOYEE"."EMPLOYEE_ID" IS 'Идентификатор сотрудника';
COMMENT ON COLUMN "EMPLOYEE"."DEPARTMENT_ID" IS 'Идентификатор отдела';
COMMENT ON COLUMN "EMPLOYEE"."EMPLOYEE_SURNAME" IS 'Фамилия сотрудника';
COMMENT ON COLUMN "EMPLOYEE"."EMPLOYEE_SALARY" IS 'Зарплата сотрудника';
COMMENT ON TABLE "EMPLOYEE" IS 'Сотрудник';

CREATE UNIQUE INDEX "U_IDX_EMPLOYEE" ON "EMPLOYEE" ("EMPLOYEE_ID") TABLESPACE MIRAVILD_INDEX;

ALTER TABLE "EMPLOYEE" ADD CONSTRAINT "PK_EMPLOYEE" PRIMARY KEY ("EMPLOYEE_ID")
  USING INDEX "U_IDX_EMPLOYEE" ENABLE VALIDATE;
  
ALTER TABLE "EMPLOYEE" MODIFY ("EMPLOYEE_SURNAME" CONSTRAINT NN_EMPLOYEE_SURNAME NOT NULL ENABLE);
ALTER TABLE "EMPLOYEE" MODIFY ("EMPLOYEE_SALARY" CONSTRAINT NN_EMPLOYEE_SALARY NOT NULL ENABLE);

ALTER TABLE "EMPLOYEE" ADD CONSTRAINT "FK_DEPARTMENT_EMPLOYEE" FOREIGN KEY ("DEPARTMENT_ID") 
REFERENCES "DEPARTMENT" ("DEPARTMENT_ID") ENABLE;
/

Заполним таблицы тестовыми данными:

INSERT INTO department d
  (d.department_id, d.department_name)
VALUES
  (1, 'отдел №1');

INSERT INTO department d
  (d.department_id, d.department_name)
VALUES
  (2, 'отдел №2');

INSERT INTO department d
  (d.department_id, d.department_name)
VALUES
  (3, 'отдел №3');

COMMIT WORK;
/

INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (1, 1, 'Петров', 500);

INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (2, 1, 'Петров', 700);

INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (3, 1, 'Петров', 500);
  
INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (4, 2, 'Петров', 100);
  
INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (5, 2, 'Петров', 300);
  
INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (6, 2, 'Сидоров', 200);
  
INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (7, 2, 'Иванов', 100);
  
INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (8, 1, 'Иванов', 1500);

INSERT INTO employee e
  (e.employee_id, e.department_id, e.employee_surname, e.employee_salary)
VALUES
  (9, 1, 'Иванов', 1500);

COMMIT WORK;
/

1. Вывести список всех отделов, указав для каждого отдела суммарную зарплату и отсортировав по этой суммарной зарплате по убыванию.

SELECT d.department_name, SUM(e.employee_salary) AS sum_salary
  FROM department d
  LEFT JOIN employee e
    ON e.department_id = d.department_id
 GROUP BY d.department_name
 ORDER BY sum_salary DESC NULLS LAST;
/
SELECT DISTINCT d.department_name,
                SUM(e.employee_salary) over(PARTITION BY d.department_name) AS sum_salary
  FROM department d
  LEFT JOIN employee e
    ON e.department_id = d.department_id
 ORDER BY sum_salary DESC NULLS LAST;
/

2. Вывести по убыванию список всех отделов, указав для каждого отдела количество сотрудников.

SELECT d.department_name, COUNT(e.employee_id) AS cnt_employee
  FROM department d
  LEFT JOIN employee e
    ON e.department_id = d.department_id
 GROUP BY d.department_name
 ORDER BY d.department_name DESC;
/
SELECT DISTINCT d.department_name,
                COUNT(e.employee_id) over(PARTITION BY d.department_name) AS cnt_employee
  FROM department d
  LEFT JOIN employee e
    ON e.department_id = d.department_id
 ORDER BY d.department_name DESC;
/

3. Вывести список всех отделов, где нет сотрудников.

SELECT d.department_name
  FROM department d
  LEFT JOIN employee e
    ON e.department_id = d.department_id
 WHERE e.employee_id IS NULL;
/

SELECT d.department_name
  FROM department d
 WHERE NOT EXISTS
 (SELECT 1 FROM employee e WHERE e.department_id = d.department_id);
/

SELECT d.department_id
  FROM department d
MINUS
SELECT e.department_id
  FROM employee e;
/

4. Вывести список отделов, в названии которых присутствует слово «отдел» и, где только у двоих сотрудников зарплата больше 1000.

SELECT d.department_name
  FROM department d
  JOIN employee e
    ON e.department_id = d.department_id
 WHERE d.department_name LIKE '%отдел%'
   AND e.employee_salary > 1000
 GROUP BY d.department_name
HAVING COUNT(*) = 2;
/

5. Вывести список отделов с указанием суммы зарплаты, где в каждом отделе не менее двух сотрудников с разными фамилиями.

SELECT d.department_name, SUM(e.employee_salary) AS sum_salary
  FROM department d
  JOIN employee e
    ON e.department_id = d.department_id
 GROUP BY d.department_name
HAVING COUNT(DISTINCT e.employee_name) >= 2;
/

P.S.
Конфигурация СУБД — Oracle Database 11g Express Edition Release 11.2.0.2.0
IDE — PL/SQL Developer Version 11.0.6.1776

Tags: , , ,

Leave a Reply

You must be logged in to post a comment.