Univerza V Ljubljani Fakulteta Za Fakulteta Za Računalništvo in Informatiko

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 13

UNIVERZA V LJUBLJANI

FAKULTETA ZA FAKULTETA ZA RAČUNALNIŠTVO IN INFORMATIKO

Seminarska naloga

Brin Perovšek Moravec

Vpisna številka: 04220142

Ljubljana, Maj 2023


1. Napišite SQL skripto za ustvarjanje tabel dept_manager in salaries. Ustvarjeni tabeli naj
vsebujeta primarne in tuje ključe ter omejitev, da datum v polju to_date ne sme biti manjši od
datuma v polju from_date. Polje to_date je lahko tudi prazno (vrednost NULL).

Tabela dept_manager:

CREATE TABLE dept_manager (

dept_no CHAR(4) NOT NULL,

emp_no INT(11) NOT NULL,

from_date DATE NOT NULL,

to_date DATE,

PRIMARY KEY (dept_no, emp_no),

FOREIGN KEY (emp_no) REFERENCES employees (emp_no),

FOREIGN KEY (dept_no) REFERENCES departments (dept_no),

CHECK (to_date IS NULL OR to_date >= from_date)

);

Tabela salaries:

CREATE TABLE salaries (

emp_no INT(11) NOT NULL,

salary INT(11) NOT NULL,

from_date DATE NOT NULL,

to_date DATE,

PRIMARY KEY (emp_no),

FOREIGN KEY (emp_no) REFERENCES employees (emp_no),

CHECK (to_date IS NULL OR to_date >= from_date)

);

Obstoječa zbirka podatkov obravnava nezaključene časovne intervale na poseben način.


Opišite kateri? Opišite tudi kako bi lahko alternativno zaključili te intervale, ter kakšne so
prednosti/slabosti teh dveh pristopov.

Če je časovni interval nezaključen, uporabi vrednost NULL, kar pomeni da je delavec še vedno na
istem oddelku. Prednost tega je, da se hitro vidi, kdo je še zaposlen v oddelku in omogoča preprosti
način, da jih najdeš. Slabosti uporabe null pa je, da porabi malo več prostora kot bi ga fiksna
vrednost, ter da moramo za določene operacije preverjati če je vrednost null (IS/IS Not NULL )

2. a) Ustvarite pogled (CREATE VIEW) place_in_nazivi, ki bo prikazal združene podatke iz tabel


employees, salaries in titles, tako da pri normalizacji tega pogleda ne bo izgubjenih ali
podvojenih podatkov. Nato ustvarite še pogled pogled_nazivi, ki bo črpal podatke iz pogleda
place_in_nazivi in prikaže enake podatke, kot jih vsebuje tabela titles. Namig: Pazite na imena
stolpcev. (5%)

CREATE VIEW place_in_nazivi AS


SELECT
e.emp_no,
e.birth_date,
e.first_name,
e.last_name,
e.gender,
e.hire_date,
e.years_working,
t.title,
t.from_date AS Tfrom_date,
t.to_date AS Tto_date,
s.salary,
s.from_date AS Sfrom_date,
s.to_date AS Sto_date
FROM
employees e
JOIN salaries s ON e.emp_no = s.emp_no
JOIN titles t ON e.emp_no = t.emp_no

CREATE VIEW pogled_nazivi AS


SELECT emp_no, title, Tfrom_date as from_date, Tto_date as to_date
FROM place_in_nazivi;

2.b) Z uporabo CTE preverite, če pogled pogled_nazivi in tabela titles vsebujeta enake vrstice.
CTE naj prikaže vrstice, ki se ne ujemajo. (10%)
WITH cte_titles AS (

SELECT title, emp_no, from_date, to_date

FROM titles

), cte_pogled_nazivi AS (

SELECT title, emp_no, Tfrom_date, Tto_date


FROM pogled_nazivi

SELECT title, emp_no, from_date, to_date

FROM cte_titles

WHERE (title, emp_no, from_date, to_date) NOT IN (

SELECT title, emp_no, Tfrom_date, Tto_date

FROM cte_pogled_nazivi

);

2.c *S pomočjo ustreznih DDL ukazov ustvarite tabelo top3(dept_no, SteviloZaposlenih), ki


hrani le 3 oddelke z največ zaposlenimi. Dodajte bazne prožilce tako, da se bo lista
posodobila vsakič, ko se spremeni število zaposlenih. (10%).

DELIMITER //

CREATE TRIGGER sproz_2c_insert

AFTER INSERT ON employees

FOR EACH ROW

BEGIN

DELETE FROM top3;

INSERT INTO top3

SELECT de.dept_no, COUNT(*)

FROM employees e

JOIN dept_emp de ON e.emp_no = de.emp_no

GROUP BY de.dept_no

ORDER BY COUNT(*) DESC

LIMIT 3;

END //

DELIMITER ;
DELIMITER //

CREATE TRIGGER sproz_2c_delete

AFTER DELETE ON employees

FOR EACH ROW

BEGIN

DELETE

FROM top3;

INSERT INTO top3

SELECT de.dept_no, COUNT(*)

FROM employees e

JOIN dept_emp de

ON e.emp_no = de.emp_no

GROUP BY de.dept_no

ORDER BY COUNT(*) DESC

LIMIT 3;

END //

DELIMITER ;

Trigger še za dept_emp

DELIMITER //

CREATE TRIGGER sproz_2c_insert_demp_emp

AFTER INSERT ON dept_emp

FOR EACH ROW

BEGIN

DELETE

FROM top3;
INSERT INTO top3

SELECT de.dept_no, COUNT(*)

FROM employees e

JOIN dept_emp de

ON e.emp_no = de.emp_no

GROUP BY de.dept_no

ORDER BY COUNT(*) DESC

LIMIT 3;

END //

DELIMITER ;

DELIMITER //

CREATE TRIGGER sproz_2c_delete_dept_emp

AFTER DELETE ON dept_emp

FOR EACH ROW

BEGIN

DELETE

FROM top3;

INSERT INTO top3

SELECT de.dept_no, COUNT(*)

FROM employees e

JOIN dept_emp de

ON e.emp_no = de.emp_no

GROUP BY de.dept_no

ORDER BY COUNT(*) DESC

LIMIT 3;

END //

DELIMITER ;
3. a) Med katerimi leti obstajajo podatki za plače v bazi? Napišite eno poizvedbo, ki vam poda
odgovor?

SELECT MIN(YEAR(from_date)) AS najman_leto, MAX(YEAR(from_date)) AS naj_leto

FROM salaries;

3 b) Katerih 10 zaposlenih je dobilo največje izplačilo. Izpišite priimke, imena in največje


izplačilo, ter izpis uredite po priimku in imenu.

SELECT e.last_name, e.first_name, s.naj_placa

FROM employees e

JOIN (

SELECT emp_no, MAX(salary) AS naj_placa

FROM salaries s

GROUP BY emp_no

) s USING (emp_no)

ORDER BY e.last_name ASC, e.first_name ASC

LIMIT 10;
3 c) Koliko je bila povprečna starost vseh zaposlenih na dan 1.1.2000.

SELECT AVG(TIMESTAMPDIFF(YEAR, birth_date, '2000-01-01')) AS povp_starost

FROM employees;

3 d) Koliko časa v letih (lahko uporabite decimalna števila) je bila zaposlena vsaka oseba v tem
podjetju. Poleg časa izpišite tudi zaposlenčevo šifro, ime in priimek.

SELECT emp_no,first_name,last_name, TIMESTAMPDIFF(YEAR, hire_date, '2002-08-01') AS


cas_zap

FROM employees

3 e) Izpišite imena in priimke zaposlenih, katerih imena se začnejo na dva zaporedna


samoglasnika, priimki pa kjerkoli v priimku vsebujejo dva zaporedna samoglasnika in se ne končajo
na samoglasnik.

SELECT first_name, last_name

FROM employees

WHERE first_name REGEXP '^[aeiou]{2}' AND last_name REGEXP '[aeiou]{2}'

AND last_name NOT REGEXP '[aeiou]$';


3 f) Za dan 1.1.1990 želimo izpisati najmlajše zaposlene. Izpišite imena, priimke in njihovo
starost v letih. Urejeno padajoče po starosti. Pozor: Urejeni naj ne bodo le na letnico starosti.

SELECT first_name, last_name, TIMESTAMPDIFF(YEAR, birth_date, '1990-01-01') AS starost

FROM employees ORDER BY starost DESC, last_name ASC;

3 g) Za vsakega zaposlenega ugotovite njegovo tedensko plačo in število dni zaposlitve. Izpišite
zaposlenčevo šifro, tedensko plačo in število dni zaposlitve padajoče po tedenski plači.

SELECT emp_no,salary/52 as tedenska_placa, DATEDIFF('2002-08-01',hire_date) as st_dni_zap

FROM employees e JOIN salaries using (emp_no)

ORDER BY tedenska_placa DESC


3 h) Kateri oddelki imajo zaposlenih nadpovprečno število žensk?*
SELECT d.dept_name

FROM departments d

JOIN ( SELECT de.dept_no, COUNT(*) AS zaposlena_zenska

FROM dept_emp de JOIN employees e USING (emp_no)

WHERE e.gender = 'F'

GROUP BY de.dept_no

) AS zaposlene_zenske USING (dept_no) JOIN (

SELECT AVG(zaposlena_zenska) AS povprecje

FROM (

SELECT de.dept_no, COUNT(*) AS zaposlena_zenska

FROM dept_emp de

JOIN employees e USING (emp_no)

WHERE e.gender = 'F'

GROUP BY de.dept_no

) AS _

) AS povprecja_vsega

WHERE zaposlene_zenske.zaposlena_zenska > povprecja_vsega.povprecje;


3 i) Izpišite imena zaposlenih, ki so delali natanko na enem oddelku in niso bili vodje
(managers). Izpis uredite po naraščajoči starosti zaposlenega in imenu.

SELECT e.first_name

FROM employees e

JOIN dept_emp de USING (emp_no)

LEFT JOIN dept_manager dm ON e.emp_no = dm.emp_no

GROUP BY e.emp_no

HAVING COUNT(DISTINCT de.dept_no) = 1

AND MAX(dm.emp_no) IS NULL

ORDER BY e.birth_date ASC, e.first_name ASC;

3 j) Imate naslednjo poizvedbo:

SELECT *

FROM salaries

WHERE from_date >= ‘1990-01-01’

ORDER BY from_date ASC;


Pospešite izvajanje te poizvedbe. Ustvarite potrebne strukture za pohitritev poizvedbe in
primerjajte čase izvajanja. Ugotovite faktor pohitritve in v poročilo zapišite čas izvajanja pred in po
pohtritvi ter faktor pohitritve. (za čas lahko uporabite ukaz set profiling=1; vaš sql; show profiles;).

CREATE INDEX index_from_date ON salaries (from_date);

SET profiling = 1;

SELECT *

FROM salaries USE INDEX (index_from_date)

WHERE from_date >= '1990-01-01'

ORDER BY from_date ASC;

Hitrost z indeksom

hitrost brez indeksa

Faktor pohitritve je 0.00966610 / 0.00732600 = 1.3194

4.) V programskem jeziku Python napišite program, ki se poveže na podatkovno bazo in za vsak
posamezen oddelek izračuna število zaposlenih v določenemu letu in mesecu. Rezultate izračunanih
števil zaposlenih za vsak oddelek, leto in mesec shranite v tabelo SteviloZaposlenih(dept_no, year,
month, no_employed).

Prvo sem ustvaril povezavo z domačo bazo in naredil cursor. Potem sem naredil tabelo SteviloZaposlenih,
če še ni obstajala, če je jo pa zbrišem in na naredim novo. Po commitu sem napisal sql stavek, ki izračuna
število zaposlenih za vsak oddelek, leto in mesec ter ga vstavi v tabelo "SteviloZaposlenih".Tabelo
"dept_emp" sem združil z tabelo "employees" z uporabo "emp_no", Rezultate sem potem še grupiral.
Potem rabiš samo še izvršiti proizvedbo in potrditi spremembe v podatkovni bazi. Nato še zaprem cursor.

4.

You might also like