- Tworzenie tabeli osoby2
create table osoby2 ( id_osoby int not null AUTO_INCREMENT, primary key (id_osoby), imie varchar(40) not null, nazwisko varchar(60) not null, data_ur datetime null, wiek int );
- Modyfikacja rekordów, zmiana id firmy
UPDATE ETATY SET id_firmy = '1000' WHERE id_firmy = '1';
- Wstawianie do tabeli
insert into osoby2 (imie,nazwisko) values ('maciej','s');
- Pokazać osoby, ich miasto zamieszkania, ich pensję i miasto firmy w której pracują
SELECT o.imie, o.nazwisko, m.nazwa as miasto_osoby, e.pensja, mf.nazwa as miasto_firmy FROM osoby o JOIN miasta m ON m.id_miasta = o.id_miasta JOIN etaty e ON e.id_osoby = o.id_osoby JOIN firmy f ON f.nazwa_skr = e.id_firmy JOIN miasta mf ON mf.id_miasta = f.id_miasta;
SQL SELECT Statement
SQL SELECT DISTINCT Statement
SQL JOIN
SQL Aliases - Pokazać osoby które aktualnie nie pracują
SELECT * FROM osoby o WHERE o.id_osoby NOT IN ( SELECT id_osoby FROM etaty e WHERE e.do IS NULL );
- Pokazać osoby które nigdy nie pracowały w firmach z miasta Warszawa
SELECT * FROM osoby o WHERE o.id_osoby NOT IN ( SELECT e.id_osoby FROM etaty e JOIN firmy f ON f.nazwa_skr = e.id_firmy JOIN miasta m ON m.id_miasta = f.id_miasta WHERE m.nazwa LIKE 'Warszawa' );
- Pokazać listę osób i jeśli pracują to ich płace
SELECT o.imie, o.nazwisko, e.pensja FROM osoby o JOIN etaty e ON e.id_osoby = o.id_osoby WHERE e.do IS NULL UNION SELECT imie, nazwisko, NULL FROM osoby WHERE id_osoby NOT IN ( SELECT o.id_osoby FROM osoby o JOIN etaty e ON e.id_osoby = o.id_osoby WHERE e.do IS NULL );
- Pokazać największą pensję w bazie i kto tyle zarabia
SELECT o.imie, o.nazwisko, e.pensja FROM osoby o JOIN etaty e ON e.id_osoby = o.id_osoby WHERE e.pensja = ( SELECT max(pensja) FROM etaty );
- Pokazać osoby z pensją większą od średniej
SELECT o.imie, o.nazwisko, e.pensja FROM osoby o JOIN etaty e ON e.id_osoby = o.id_osoby WHERE e.pensja > ( SELECT avg(pensja) FROM etaty );
- Pokazać 2 największe pensje oraz osoby, które tyle zarabiają
SELECT o.imie, o.nazwisko, e.pensja FROM osoby o JOIN etaty e ON e.id_osoby = o.id_osoby ORDER BY e.pensja DESC LIMIT 2;
SQL ORDER BY Keyword
SQL SELECT TOP Equivalent
- Pokazać największe pensje w każdej firmie i kto tyle zarabia
SQL GROUP BY Statement-
SELECT o.imie, o.nazwisko, e.pensja, e.id_firmy, m.maks FROM osoby o JOIN etaty e ON e.id_osoby = o.id_osoby JOIN ( SELECT e.id_firmy, max(e.pensja) AS maks FROM etaty e GROUP BY e.id_firmy) m ON e.pensja = m.maks;
-
SELECT o.imie, o.nazwisko, e.pensja, e.id_firmy, m.maks FROM osoby o JOIN etaty e ON e.id_osoby = o.id_osoby JOIN ( SELECT e.id_firmy, max(e.pensja) AS maks FROM etaty e GROUP BY e.id_firmy) m ON m.id_firmy = e.id_firmy WHERE e.pensja = m.maks
-
- Pokazać wszystkie firmy, średnie pensje w nich, ile osób pracujących, ile etatów
-
SELECT e.id_firmy, avg(e.pensja) AS srednia, count(*) AS ile_etatow, sum(e.do IS NULL) AS ile_osob FROM etaty e JOIN firmy f ON f.nazwa_skr = e.id_firmy GROUP BY e.id_firmy
-
SELECT DISTINCT e.id_firmy, m.srednia, m2.ile_osob, m3.ile_etatow FROM etaty e JOIN ( SELECT e.id_firmy, avg(e.pensja) AS srednia FROM etaty e GROUP BY e.id_firmy) m ON m.id_firmy = e.id_firmy JOIN ( SELECT e.id_firmy, count(*) AS ile_osob FROM etaty e WHERE e.do IS NULL GROUP BY e.id_firmy) m2 ON m2.id_firmy = e.id_firmy JOIN ( SELECT e.id_firmy, count(*) AS ile_etatow FROM etaty e GROUP BY e.id_firmy) m3 ON m3.id_firmy = e.id_firmy
-
- Pokazać średnią pensję w firmach z woj Mazowieckiego zatrudniających powyżej 10 osób (praca domowa)
select AVG(e.pensja), f.nazwa_skr, COUNT(e.id_etatu) from etaty e inner join osoby o on o.id_osoby = e.id_osoby inner join firmy f on f.nazwa_skr = e.id_firmy inner join miasta m on m.id_miasta = f.id_miasta inner join woj w on w.kod_woj = m.kod_woj where e.do is null and w.nazwa = 'Mazowieckie' group by f.nazwa_skr having 10 > COUNT(e.id_etatu)
- Pokazać osoby mające aktualnie powyżej jednego etatu [imię, nazwisko, id_osoby, liczba etatów]
SELECT o.id_osoby, o.imie, o.nazwisko, sum(e.do IS NULL AND e.id_osoby IS NOT NULL) as ile_aktualnych FROM osoby o LEFT JOIN etaty e ON e.id_osoby=o.id_osoby GROUP BY o.id_osoby, o.imie, o.nazwisko HAVING ile_aktualnych > 1
- Pokazać województwa mające powyżej 2 miast [kod i nazwa województwa, liczba miast]
select w.kod_woj, w.nazwa, count (*) as liczba_miast from woj w join miasta m on m.kod_woj=w.kod_woj group by w.kod_woj, w.nazwa having count (w.kod_woj) > 2;
- Ilość etatów w województwach, ale tylko w tych, w których mieszka co najmniej 1 osoba i istnieje co najmniej 1 firma, w której nie pracuje Stodolski (bez rozwiązania)
- Napisać procedurę bazodanową wyszukiwania osób po imieniu
(podaną w parametrze)
DROP PROCEDURE IF EXISTS Szukaj; DELIMITER // CREATE PROCEDURE Szukaj (IN imie_n VARCHAR(20)) BEGIN SELECT osoby.imie, osoby.nazwisko, miasta.nazwa FROM osoby LEFT JOIN miasta ON miasta.id_miasta=osoby.id_miasta WHERE osoby.imie=imie_n; END// DELIMITER ; CALL Szukaj('Maciej');
- Napisać procedurę bazodanową, która ma parametr @kod_woj char(4) i dla tego parametru zwraca listę firm i średnią pensję w każdej z nich (firmy z tego województwa) [nazwa woj, nazwa firmy, nazwa_skr, Sr_pensja]
DROP PROCEDURE IF EXISTS Szukaj_woj; DELIMITER // CREATE PROCEDURE Szukaj_woj (IN kod CHAR(4)) BEGIN SELECT w.nazwa, f.nazwa, f.nazwa_skr, avg(e.pensja) FROM woj w LEFT JOIN miasta m ON m.kod_woj=w.kod_woj LEFT JOIN firmy f ON f.id_miasta=m.id_miasta LEFT JOIN etaty e ON e.id_firmy=f.nazwa_skr WHERE w.kod_woj=kod GROUP BY 1,2,3; END// DELIMITER ; CALL Szukaj_woj('Maz'); CALL Szukaj_woj('???');
- Napisać funkcję bazodanową sprawdzającą czy miasto istnieje po nazwie (podanej w parametrze).
DROP FUNCTION IF EXISTS czy_miasto_istnieje; DELIMITER // CREATE FUNCTION czy_miasto_istnieje(nazwa_m VARCHAR(30)) RETURNS INT BEGIN IF(EXISTS(SELECT * FROM miasta m WHERE m.nazwa=nazwa_m)) then RETURN 1; END IF;RETURN 0; END // DELIMITER ; Select czy_miasto_istnieje('WARSZAWA') as czy_WARSZAWA, czy_miasto_istnieje('Warszawa') czy_Warszawa, czy_miasto_istnieje('Poznan') czy_Poznan;
- Napisać funkcję bazodanową, która dla parametru @nazwa_miasta varchar(20) policzy ile osób mieszka w danym mieście. Jeśli miasto nie istnieje to należy zwrócić ilość osób=-1.
DROP FUNCTION IF EXISTS ile_osob; DELIMITER // CREATE FUNCTION ile_osob(nazwa_m VARCHAR(30)) RETURNS INT BEGIN IF(EXISTS(SELECT * FROM miasta m WHERE m.nazwa=nazwa_m)) then RETURN ( SELECT count(o.id_osoby) FROM miasta m LEFT JOIN osoby o ON o.id_miasta=m.id_miasta WHERE m.nazwa=nazwa_m ); END IF; RETURN -1; END // DELIMITER ; SELECT m.nazwa, ile_osob(m.nazwa) FROM miasta m;
- Napisać procedurę bazodanową liczącą średnią pensję w miastach w województwie o kodzie w parametrze.
- Napisać procedurę, która policzy liczbę mieszkańców w mieście, pod warunkiem że istnieje w tym mieście firma o zadanym ID.
- [PRACA DOMOWA] Napisać procedurę składowaną, która dla podanego miasta jako parametru wypisze statystyki: ile osób mieszka, ile mieszkających osób jest zatrudnionych, ile jest firm, ile osób jest zatrudnionych w tych firmach, ile jest w tych firmach etatów [jeden wiersz ze wszystkimi statystykami] (bez rozwiązania).
- Napisać TRIGGER związany z tabelą osoby (polecenia INSERT i UPDATE), który przepisuje imię i nazwisko do pola ALIAS w tabeli osoby biorąc pierwszą literę imienia, kropka, spacja, cale nazwisko. Proszę pamiętać o uniknięciu rekurencji (trigger bomb).
a) dodanie kolumny aliasALTER TABLE osoby ADD alias varchar(20) NULL;
b) stworzenie triggera INSERT
DROP TRIGGER IF EXISTS wstaw_alias; DELIMITER // CREATE TRIGGER wstaw_alias BEFORE INSERT ON osoby FOR EACH ROW BEGIN SET NEW.alias = (concat(left(NEW.imie,1),'. ' ,NEW.nazwisko)); END // DELIMITER ;
c) stworzenie triggera UPDATE
DROP TRIGGER IF EXISTS update_alias; DELIMITER // CREATE TRIGGER update_alias BEFORE UPDATE ON osoby FOR EACH ROW BEGIN SET NEW.alias = (concat(left(NEW.imie,1),'. ' ,NEW.nazwisko)); END // DELIMITER ;
d) wstawienie osoby i aktualizacja innej
INSERT INTO osoby (id_miasta,imie,nazwisko) VALUES (2,'Jan','Kowalski'); UPDATE osoby SET imie='Maciej' WHERE id_osoby=1;
e)aktualizacja „niebezpieczna” – błąd „Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column”
-- aby dopuścić tryb bezpieczny SET SQL_SAFE_UPDATES=0; UPDATE osoby SET imie='Juz' WHERE imie='Juz'; -- po wykonaniu należy przywrócić tryb bezpieczny SET SQL_SAFE_UPDATES=1;
f) wypisanie wyników
SELECT * FROM osoby;
- Stworzyć trigger INSERT, który nie pozwoli dodać do bazy osoby o nazwisku 'Stodolski’.
DROP TRIGGER IF EXISTS nie_stodolski; DELIMITER // CREATE TRIGGER nie_stodolski BEFORE INSERT ON osoby FOR EACH ROW BEGIN IF NEW.nazwisko='Stodolski' THEN signal sqlstate '45000' set message_text = 'Stodolski niemile widziany'; END IF; END // DELIMITER ; INSERT INTO osoby (id_miasta,imie,nazwisko) VALUES (2,'Jan','Stodolski'); -- Error Code: 1644. Stodolski niemile widziany
- Stworzyć trigger UPDATE, który nie pozwoli dodać do bazy dwa razy tego samego miasta w tym samym województwie (np. Warszawa może być tylko jedna w województwie mazowieckim). Wypisać w błędzie wiadomości jakich nazw miast w jakich województwach nie da się zamienić, np. „Nie można zamienić WARSZAWA w województwie MAZ na Wesola w województwie MAZ”.
DROP TRIGGER IF EXISTS rozne_miasta; DELIMITER // CREATE TRIGGER rozne_miasta BEFORE UPDATE ON miasta FOR EACH ROW BEGIN DECLARE msg varchar(128); SET msg = (concat('Nie można zamienić ', OLD.nazwa, ' w województwie ', OLD.kod_woj, ' na ',NEW.nazwa, ' w województwie ',NEW.kod_woj)); IF (EXISTS(SELECT * FROM miasta WHERE nazwa=NEW.nazwa AND kod_woj = NEW.kod_woj)) THEN signal sqlstate '45000' set message_text = msg; END IF; END // DELIMITER ; UPDATE miasta SET nazwa='Wesola' WHERE kod_woj='Maz' AND nazwa='Warszawa'; -- Error Code: 1644. Nie można zamienić WARSZAWA -- w województwie MAZ na Wesola w województwie MAZ
- Napisać skrypt, który:
a) doda kolumnę do tabeli woj ile_miast z domyślną wartością 0ALTER TABLE woj ADD ile_miast int NULL default 0;
b) utworzy trigger, który automatycznie po dodaniu miasta uzupełni dane w tej kolumnie
DROP TRIGGER IF EXISTS ile_miast; DELIMITER // CREATE TRIGGER ile_miast AFTER INSERT ON miasta FOR EACH ROW BEGIN DECLARE ile_m INT; SET ile_m=( SELECT count(m.id_miasta) FROM woj w LEFT JOIN miasta m ON m.kod_woj=w.kod_woj WHERE w.kod_woj = NEW.kod_woj ); UPDATE woj SET ile_miast=ile_m WHERE kod_woj = NEW.kod_woj; END // DELIMITER ; INSERT INTO miasta (kod_woj,nazwa) VALUES ('Pom','Gdynia'); INSERT INTO miasta (kod_woj,nazwa) VALUES ('Maz','Łomianki'); SELECT * FROM woj;
- Stwórz skrypt, który
a) Utworzy tabelę zmiany_etatow z polami: id_etatu, data_aktualizacji i nazwa_uzytkownika.CREATE TABLE zmiany_etatow ( id_etatu INT NOT NULL, data_aktualizacji DATE NOT NULL, nazwa_uzytkownika varchar(50) NOT NULL );
lub
CREATE TABLE zmiany_etatow_ts ( id_etatu INT NOT NULL, data_aktualizacji TIMESTAMP, nazwa_uzytkownika varchar(50) NOT NULL );
b) Utworzy trigger UPDATE, który będzie monitorował zmiany w tabeli etaty.
Trigger powinien do tabeli zmiany_etatów wprowadzać następujące dane: id_etatu, który został zmieniony, datę wprowadzenia zmiany i jaki użytkownik zmianę wprowadził.
Wskazówka: W rozwiązaniu można użyć funkcji USER() i SYSDATE().DROP TRIGGER IF EXISTS update_etaty; DELIMITER // CREATE TRIGGER update_etaty AFTER UPDATE ON etaty FOR EACH ROW BEGIN DECLARE uzytkownik varchar(50); SELECT USER() INTO uzytkownik; INSERT INTO zmiany_etatow (id_etatu, data_aktualizacji, nazwa_uzytkownika) VALUES ( NEW.id_etatu, SYSDATE(), uzytkownik); END; // DELIMITER ; UPDATE etaty SET pensja=123456 WHERE id_etatu=1; SELECT * from zmiany_etatow;
lub
DROP TRIGGER IF EXISTS update_etaty; DELIMITER // CREATE TRIGGER update_etaty AFTER UPDATE ON etaty FOR EACH ROW BEGIN DECLARE uzytkownik varchar(50); SELECT USER() INTO uzytkownik; INSERT INTO zmiany_etatow_ts (id_etatu, nazwa_uzytkownika) VALUES ( NEW.id_etatu, uzytkownik); END; // DELIMITER ; UPDATE etaty SET pensja=123456 WHERE id_etatu=1; SELECT * from zmiany_etatow_ts;
- Stwórz trigger INSERT, który policzy wartość wstawionych pensji do tabeli etaty. Pokaż działanie wstawiając parę rekordów.
DROP TRIGGER IF EXISTS licz_pensje; DELIMITER // CREATE TRIGGER licz_pensje AFTER INSERT ON etaty FOR EACH ROW SET @suma_pensji = @suma_pensji + NEW.pensja; // DELIMITER ; SET @suma_pensji = 0; INSERT INTO etaty ( id_osoby, id_firmy, pensja, od, do ,stanowisko) VALUES ( 1, 'UKSW', 4700, '2000-01-02', NULL, 'Profesor'), ( 1, 'UKSW', 5700, '2002-01-02', '2004-01-01', 'Dziekan'), ( 1, 'UKSW', 6700, '2004-01-02', '2006-01-01', 'Rektor'); SELECT @suma_pensji AS 'Suma wstawionych pensji';
- Stwórz trigger INSERT, który policzy wartość wstawionych pensji do tabeli etaty – oddzielnie dla etatów zakończonych i etatów aktywnych. Pokaż działanie wstawiając parę rekordów.
DROP TRIGGER IF EXISTS licz_pensje; DELIMITER // CREATE TRIGGER licz_pensje AFTER UPDATE ON etaty FOR EACH ROW SET @suma_nieaktywnych = @suma_nieaktywnych + IF(NEW.do IS NOT NULL, NEW.pensja, 0), @suma_aktywnych = @suma_aktywnych + IF(NEW.do IS NULL, NEW.pensja, 0); // DELIMITER ; SET @suma_nieaktywnych = 0; SET @suma_aktywnych = 0; INSERT INTO etaty ( id_osoby, id_firmy, pensja, od, do ,stanowisko) VALUES ( 1, 'UKSW', 4700, '2000-01-02', NULL, 'Profesor'), ( 1, 'UKSW', 5700, '2002-01-02', '2004-01-01', 'Dziekan'), ( 1, 'UKSW', 6700, '2004-01-02', '2006-01-01', 'Rektor'); SELECT @suma_nieaktywnych AS 'Suma nieaktywnych pensji', @suma_aktywnych AS 'Suma aktywnych pensji';
- [PRACA DOMOWA] Stwórz skrypt, który
a) Utworzy tabelę studenci z polami: id_studenta (auto incerement), imie, nazwisko, ocena (wartość domyślna 'brak’)
b) Wstaw kilku studentów
c) Stwórz trigger UPDATE dla tabeli studenci, który na podstawie punktów z 4 laboratoriów wystawi ocenę w tej tabeli (’bardzo dobry’, 'dobry +’, 'dobry’, 'dostateczny +’, 'dostateczny’, 'niedostateczny’) wg odpowiednich progów procentowych. Załóż, że student może dostać maksymalnie 48 pkt.
Przykład wywołania:UPDATE studenci SET lab1=12, lab2=10, lab3=8, lab4=6 WHERE id_studenta=1;
- Napisać skrypt, który:
a) doda kolumnę tekstową miasta_w_województwach w tabeli „woj”
b) doda trigger INSERT do tabeli „miasta”, który przy dodaniu nowego miasta zaktualizuje pole miasta_w_województwach w tablicy „woj” wpisując wszystkie miasta z danego województwa rozdzielone średnikiem
c) należy sprawdzić działanie tego triggera na paru przykładach
ALTER TABLE woj ADD miasta_w_woj varchar(1024) NULL; DROP TRIGGER IF EXISTS nazwy_miast; DELIMITER // CREATE TRIGGER nazwy_miast AFTER INSERT ON miasta FOR EACH ROW BEGIN DECLARE nazwy varchar(1024); SET nazwy=( SELECT GROUP_CONCAT( DISTINCT m.nazwa ORDER BY m.nazwa SEPARATOR ';') FROM miasta m WHERE m.kod_woj=NEW.kod_woj ); UPDATE woj SET miasta_w_woj=nazwy WHERE kod_woj = NEW.kod_woj; END // DELIMITER ; INSERT INTO miasta (kod_woj,nazwa) VALUES ('Pom','XXX'); INSERT INTO miasta (kod_woj,nazwa) VALUES ('Maz','YYY'); SELECT * FROM woj;
- Napisać zapytanie SQL, które dla kolumny pensja w tabeli etaty wypisze jak dużo zarabia dana osoba:
– pensja <1000 -> „mało”
– pensja >=1000 i <5000 -> „średnio”
– pensja >=5000 i <15000 -> „dużo”
– pensja >=15000 „bardzo dużo”SELECT id_osoby, pensja, CASE WHEN pensja < 1000 THEN 'mało' WHEN pensja >= 1000 AND pensja < 5000 THEN 'średnio' WHEN pensja >= 5000 AND pensja < 15000 THEN 'dużo' ELSE 'bardzo dużo' END as jak_zarabia FROM etaty;
- Napisać zapytanie SQL, które zwróci odchylenie standardowe w populacji dla kolumny pensja bez użycia wbudowanych funkcji związanych z odchylenie standardowym (STD, STDDEV, STDEV_POP, VAR_POP, VARIANCE, VAR_SAMP).
SELECT l4.licznik/m1.mianownik, k1.sd FROM ( SELECT SQRT(l3.suma_kw) as licznik FROM ( SELECT Sum(l2.kwadrat) as suma_kw FROM ( SELECT l1.roznica*l1.roznica as kwadrat FROM ( SELECT pensja-(Select AVG(pensja) FROM etaty) as roznica FROM etaty ) l1 ) l2 ) l3 ) l4, ( SELECT SQRT(count(pensja)) as mianownik FROM etaty ) m1, ( SELECT STDDEV(pensja) as sd FROM etaty ) k1 ;
- [PRACA DOMOWA] Napisać funkcję bazodanową, która zwróci odchylenie standardowe w populacji
dla kolumny @nazwa kolumny w tabeli bez użycia wbudowanych funkcji związanych
z odchyleniem standardowym (STD, STDDEV, STDEV_POP, VAR_POP, VARIANCE,
VAR_SAMP). Nazwa kolumny i nazwa tabeli powinny być parametrami funkcji.
WSKAZÓWKA: mozna użyć fukncji PREPARE QUERY. Przykład:DROP PROCEDURE IF EXISTS zapytanie_sql; DELIMITER // CREATE PROCEDURE zapytanie_sql ( columnName VARCHAR (50), tableName VARCHAR (50), whereClose VARCHAR (50)) BEGIN SET @sql_query=CONCAT('SELECT ', columnName, ' FROM ', tableName, ' WHERE ', whereClose); PREPARE QUERY FROM @sql_query; EXECUTE QUERY; END // DELIMITER ; CALL zapytanie_sql('imie', 'osoby', 'id_osoby in (1,2)');