DROP TABLE IF EXISTS employees CASCADE;
CREATE TABLE employees (
  fname varchar(255),
  minit varchar(1),
  lname varchar(255),
  sin varchar(9) primary key,
  bdate date,
  address varchar(255),
  gender varchar(1),
  salary integer,
  dno integer
);

DROP TABLE IF EXISTS departments CASCADE;
CREATE TABLE departments (
  dname varchar(255),
  dnumber integer primary key,
  mgrsin varchar(9),
  mgrstartdate date
);

DROP TABLE IF EXISTS projects CASCADE;
CREATE TABLE projects (
  pname varchar(255),
  pnumber integer primary key,
  plocation varchar(255),
  dnum integer
);

DROP TABLE IF EXISTS locations CASCADE;
CREATE TABLE locations (
  dnbr integer,
  dlocation varchar(255)
);

INSERT INTO employees VALUES ('Harris', 'T', 'Chomsky', 123, '1965-12-10', 'Edmonton', 'M', 50000, 12);
INSERT INTO employees VALUES ('Kristian', 'C', 'Bohr' , 456, '1975-10-05', 'Ottawa', 'M', 28000, 11);
INSERT INTO employees VALUES ('Charlotte', 'F', 'Bouchard' , 789, '1985-08-06', 'Montreal', 'F', 40000, 11);
INSERT INTO employees VALUES ('Said', 'J', 'Ahmad', 111, '1970-09-07', 'Toronto', 'M', 30000, 12);
INSERT INTO employees VALUES ('Andrew', 'U', 'Brahe', 222, '1970-04-02', 'Winnipeg', 'M', 20000, 10);
INSERT INTO employees VALUES ('Nadia', 'O', 'Mamary', 333, '1960-01-08', 'Saskatoon', 'F', 35000, 10);
INSERT INTO employees VALUES ('Yuan', 'P', 'Nielsen', 987, '1983-02-27', 'Moncton', 'F', 32000, 11);
INSERT INTO employees VALUES ('Neil', 'A', 'Dion', 654, '1953-02-27', 'Moncton', 'M', 32000, 11);
INSERT INTO employees VALUES ('Karen', 'C', 'Ming', 321, '1963-11-16', 'Victoria', 'F', 26000, 12);
INSERT INTO departments VALUES ('ConsProd', 10, 333, '2004-10-01');
INSERT INTO departments VALUES ('InduProd', 11, 654, '2005-05-01');
INSERT INTO departments VALUES ('Research', 12, 111, '2000-06-15');
INSERT INTO projects VALUES ('Mobile University', 1, 'Ottawa', 10);
INSERT INTO projects VALUES ('Interactive TV', 2, 'Ottawa', 12);
INSERT INTO projects VALUES ('Intelligent Agent', 3, 'Athabasca', 11);
INSERT INTO projects VALUES ('E-Commerce', 4, 'Edmonton', 10);
INSERT INTO projects VALUES ('Mobile Office', 5, 'Athabasca', 11);
INSERT INTO locations VALUES (10, 'Edmonton');
INSERT INTO locations VALUES (10, 'Ottawa');
INSERT INTO locations VALUES (11, 'Athabasca');
INSERT INTO locations VALUES (12, 'Ottawa');
INSERT INTO locations VALUES (12, 'Montreal');

-- ALTER TABLE departments ADD CONSTRAINT employees_fk FOREIGN KEY (mgrsin) REFERENCES employees (sin);
-- ALTER TABLE employees ADD CONSTRAINT departments_fk FOREIGN KEY (dno) REFERENCES departments (dnumber);
-- ALTER TABLE locations ADD CONSTRAINT departments_fk FOREIGN KEY (dnbr) REFERENCES departments(dnumber);
-- ALTER TABLE projects ADD CONSTRAINT departments_fk FOREIGN KEY (dnum) REFERENCES departments (dnumber);

CREATE OR REPLACE FUNCTION update_referenced_department_numbers() RETURNS trigger AS $$
BEGIN
  IF NEW.dnumber <> OLD.dnumber THEN
    UPDATE employees SET dno = NEW.dnumber WHERE dno = OLD.dnumber;
    UPDATE locations SET dnbr = NEW.dnumber WHERE dnbr = OLD.dnumber;
    UPDATE projects SET dnum = NEW.dnumber WHERE dnum = OLD.dnumber;
  END IF;

  RETURN NEW;
END
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS update_department_number on departments CASCADE;
CREATE TRIGGER update_department_number AFTER UPDATE
  ON departments
  FOR EACH ROW
  WHEN (OLD.dnumber <> NEW.dnumber)
  EXECUTE PROCEDURE update_referenced_department_numbers();

CREATE OR REPLACE FUNCTION update_referenced_sin_numbers() RETURNS trigger AS $$
BEGIN
  IF NEW.sin <> OLD.sin THEN
    UPDATE departments set mgrsin = NEW.sin WHERE mgrsin = OLD.sin;
  END IF;
  RETURN NEW;
END
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS update_sin ON employees CASCADE;
CREATE TRIGGER update_sin AFTER UPDATE
  ON employees
  FOR EACH ROW
  WHEN (OLD.sin <> NEW.sin)
  EXECUTE PROCEDURE update_referenced_sin_numbers();

UPDATE departments SET dnumber = 14 where dnumber = 12;

SELECT departments.dname, count(distinct(employees.sin))
FROM departments
INNER JOIN employees on employees.dno = departments.dnumber
INNER JOIN projects on projects.dnum = departments.dnumber
WHERE projects.pname LIKE 'Mobile %'
GROUP BY departments.dnumber;

SELECT d.dname, count(distinct(e.sin))
FROM departments d
INNER JOIN employees e on e.dno = d.dnumber
WHERE e.gender = 'F'
AND e.salary > 27000
GROUP BY d.dnumber;

CREATE OR REPLACE VIEW dept_summary (department_id, employees_count, total_salary, average_salary) AS
  SELECT e.dno, count(e.sin), sum(e.salary), round(avg(e.salary), 2)
  FROM employees e
  INNER JOIN departments d on d.dnumber = e.dno
  INNER JOIN projects p on p.dnum = d.dnumber
  WHERE e.dno = d.dnumber
  AND p.pname LIKE 'Mobile%'
  GROUP BY e.dno;

SELECT * FROM dept_summary;
