sapientia - erdélyi magyar tudományegyetem (emte ) marosvásárhely
DESCRIPTION
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE ) Marosvásárhely. ABR ( Adatb á zisrendszerek ) 12. El ő ad á s: 0. Egyes érdekesebb lek érdezésekről NULL értékek használata alkérdésekben Sz ámlanyilvántartási feladat megoldása Illyés László. - PowerPoint PPT PresentationTRANSCRIPT
1
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Marosvásárhely
ABR ( Adatbázisrendszerek)
12. Előadás:
0. Egyes érdekesebb lekérdezésekről 1. NULL értékek használata alkérdésekben2. Számlanyilvántartási feladat megoldása
Illyés László
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Csíkszereda
b) Keressük meg a legdrágább nyomtatókat?c) Keressük meg azokat a laptopokat, amelyek minden PC-nél lassúbbak?d) Keressük meg a modellszámát a legdrágább terméknek (PC, laptop
vagy nyomtató)
SELECT modell FROM NyomtatoWHERE ar=(SELECT MAX(ar) FROM Nyomtato);
SELECT modell FROM LaptopWHERE sebesseg< ALL (SELECT sebesseg FROM PC);
Q1=(SELECT modell,ar FROM PC) UNION (SELECT modell,ar FROM Laptop) UNION (SELECT modell,ar FROM Nyomtato);
SELECT modell FROM Q1 WHERE ar=(SELECT MAX(ar) FROM Q1)2
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Csíkszereda
e) Keressük meg a legolcsóbb színes nyomtatók gyártóit?
SELECT gyarto FROM Termek WHERE modell IN(SELECT modell FROM Nyomtato WHERE szines ANDar=(SELECT MIN(ar) FROM Nyomtato));
SELECT gyarto FROM Termek WHERE modell IN(SELECT modell FROM Nyomtato WHERE ar=(SELECT MIN(ar) FROM Nyomtato WHERE szines));
Három variáns
Melyik a jó
És miért
e1
e2
e3 SELECT gyarto FROM Termek WHERE modell IN(SELECT modell FROM Nyomtato WHERE szines AND ar=(SELECT MIN(ar) FROM Nyomtato WHERE szines));
3
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Csíkszereda
f) Keressük meg annak a PC-nek a gyártóját, amely a leggyorsabb processzorú PC-t gyártja a legkisebb memóriájú PC-k között.
Q2=SELECT gyarto, sebesseg FROM Termek INNER JOIN PC ON Termek.modell=PC.modell WHERE sebesseg IN (SELECT sebesseg FROM PC WHERE memoria=(SELECT MIN(memoria) FROM PC));
SELECT gyarto FROM Q2 WHERE sebesseg =(SELECT MAX(sebesseg) FROM Q2)
4
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Csíkszereda
d) Keressük meg a “D” gyártó által gyártott PC-k és laptopok átlagos árát?e) Keressük meg minden egyes PC-sebességéhez az ilyen sebességű PC-k átlagos árát?f) Keressük meg minden gyártó esetén a laptopok átlagos képernyőméretét?
d)Q1=(SELECT ar FROM Termek INNER JOIN PC ON Termek.modell=PC.modell WHERE Termek.gyarto=‘D’) UNION ALL (SELECT ar FROM Termek INNER JOIN Laptop ON Termek.modell=Laptop.modell WHERE Termek.gyarto=‘D’);SELECT AVG(ar) FROM Q1;
e) SELECT sebesseg, AVG(ar) FROM PC GROUP BY (sebesseg);
f) SELECT gyarto, AVG(kepernyo) FROM Termek INNER JOIN laptop ON Termek.modell=laptop.modell GROUP BY (gyarto);
5
6
CREATE TABLE table1(KOD INTEGER PRIMARY KEY, ertek INTEGER);CREATE TABLE table2(KOD INTEGER PRIMARY KEY, ertek INTEGER);INSERT INTO table1 VALUES (1,1),(2,2);INSERT INTO table2 VALUES (1,1),(2,2),(3,3),(4,4),(5,5);SELECT ertek FROM table2 WHERE ertek NOT IN (SELECT ertek FROM table1);Eredmény: 3,4,5INSERT INTO table1 VALUES (6,null); Eredmény: NULL ugyanazzal a lekérdezésselEgy megoldás:SELECT ertek FROM table2 WHERE ertek NOT IN (SELECT ertek FROM table1 WHERE ertek IS NOT null);
NULL érték használata alkérdésekben (Celko J., SQL felsőfokon, Kiskapu, 117-119)
7
Az IN predikátumot a következő képpen határozzuk meg:SELECT ertek FROM table2 WHERE NOT (ertek= ANY(SELECT ertek FROM table1));
Ebből következik, hogy:SELECT ertek FROM table2 WHERE NOT((ertek=1) OR (ertek=2) OR (ertek=3) OR (ertek=4) OR (ertek=5) OR (ertek=NULL));
DeMorgan azonosságokat alkalmazvaSELECT ertek FROM table2 WHERE((ertek<>1) AND (ertek<>2) AND (ertek<>3) AND (ertek<>4) AND (ertek<>5) AND UNKNOWN)
Eredmény mindíg UNKNOWN lesz, ami a WHERE záradékban nem lehet.
8
NULL érték kiküszöbölése a gyakorlatban
0 ismeretlen1 férfi2 nő9 N/A
Filmek
hossz
fegyver
cím év szalagFajta
azegy
azegyazegy
azegy
Rajzfilmek Bűnűgyi filmek
Hangok
Bűnűgyi Rajzfilmek
szerep
9
Film(cím, év, hossz, szalagfajta)
BűnűgyiFilm(cím, év, hossz, szalagfajta, fegyver)
Rajzfilm(cím, év, hossz, szalagfajta)
Hang(filmCím, gyártÉv, színészNév, szerep)
BűnűgyiRajzfilm(cím, év, hossz, szalagfajta, fegyver)
Egyedhalmazok összevonása nullérték használatával
Film(cím, év, hossz, szalagfajta, fegyver, hang)
Hang(filmCím, gyártÉv, színészNév, szerep)
10
Sapientia - Erdélyi Magyar Tudományegyetem (EMTE) Marosvásárhely
Egy lehetséges megkülönböztetés NULL érték használatával
Hang Fegyver Filmtipús
NULL -1 NULL “” Film
NULL -1 Érték Bűnűgyi film
0 0 NULL “” Néma rajzfilm
0 0 Érték Néma bűnűgyi rajzfilm
1 1 NULL “” Hangos rajzfilm
1 1 Érték Hangos bűnűgyi rajzfilm11
12
Feladat:
Egy cégnél adatbázisban szeretnénk tárolni a kimenő és bejövő
számlák információit. Szeretnénk tudni, hogy mindenik számlán
milyen terméket adtunk el, hogy a kimenő számlák melyik cégnek
voltak kibocsájtva, a cégek milyen kifizetéseket eszközöltek ezen
számlákra és hogy mennyivel tartoznak, vagy késésben vannak-e a
megadott határidő szerint. A határidő a számlához tartozik, nem a
céghez. Ugyanakkor nyilvántartjuk a bejövő számláinkat is, de csak
összeg szerint és a saját kifizetéseink szerint. Az ügyfeleink, a
beszállítók és a vevők egy táblában tárolódnak. A mi kifizetéseinket
is nyilvántartjuk. Egy számlára történhetnek részleges kifizetések is.
13
Zölddel írva a számla általános adatait láthatjuk
Pirossal a számlasorok attribútumai vannak
Kékkel írva láthatóak a számlasorok.
14
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Marosvásárhely
Ügyfelek
számlaszám
termékID
Számlák
számlája
sorai
mennyiség
SorszámÁFA
Számlasorok
mértékegység
egységár
Termékek
Dátum
terméke
név
határidő
azonosító
név bank bszámla
adószám bejegyzés
15
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Marosvásárhely
Az ábrához tartozó relációk:
Ugyfel(azonosito, nev, adoszam, cim, bejegyzes, bank, bszamla)
Termek(termekID, nev, mertekegyseg)
Szamla(szamlaszam, AFA, datum, hatarido, klienskod)
Szamlasor(szamlaszam, sorszam, egysegar, mennyiseg, termekID)
Mivel a Szamla a bejövő és kimenő számlákat is jelenti, még egy attribútumot adunk hozzá: összeg, amelyik az össz-számlaösszeget jelenti. Ez a kimenő számlák esetében lehet NULL, ezzel meg tudjuk különböztetni a bejövő és kimenő számlákat egymástól.
Szamla(szamlaszam, AFA, datum, hatarido, klienskod, osszeg)
16A megvalósítás ACCESS-ban
17
A számlák kifizetései ugyancsak hasonló a számlasorok struktúrához, mert a kifizetések is egy számlára vonatkoznak. Ezért gyenge egyedhalmaz.
Kifizetes(szamlaszam, sorszam, dokszam, Datum, tipus, összeg)
A tipus lehet pl. {OP, cash} vagy más (kompenzáció) stb.
Ebben nyilvantarthatjuk a mi kifizeteseinket és a nekünk fizetett összegeket is. A különbséget az adja meg, hogy milyen SZÁMLÁHOZ tartozik, a bejövőhöz-e, vagy a kimenőhöz.
számlaszám
Számlák
ÁFA
Dátum
határidőKifizetései
tipús
Sorszám
Kifizetések
összeg
dokSzam
Dátum
18
A kifizetések nyilvántartásával kiegészült ACCESS megvalósítás
19
A kimenő és bejövő számláknak nyilvántartása jobb, ha külön történik: A kimenő számláknál az összeg attribútumot kivettük, mert kiszámítható a számlasorokból. A kifizetéseket is külön vettük.
A beviteli sorrend a következő:
1. Termek, Ugyfel
2. BeSzamla, KiSzamla
3. Szamlasor, bejovoPenz, Kifizetés
20Ugyanaz OpenBaseban
21
CREATE TABLE UGYFEL(azonosito integer PRIMARY KEY,nev VARCHAR(40),cim VARCHAR(40),ADOSZAM VARCHAR(20),BEJEGYZES VARCHAR(20),BANK VARCHAR(50),BANKSZAMLA VARCHAR(40));
CREATE TABLE TERMEK(TERMEKID INTEGER PRIMARY KEY,NEV VARCHAR(50),MERTEKEGYSEG VARCHAR(30));
22
CREATE TABLE BESZAMLA(SZAMLASZAM INTEGER PRIMARY KEY,AFA INTEGER,DATUM DATE,HATARIDO DATE,UGYFELID INTEGER,OSSZEG NUMERIC(16,2),FOREIGN KEY (UGYFELID) REFERENCES
UGYFEL(AZONOSITO));
23
CREATE TABLE KISZAMLA(SZAMLASZAM INTEGER PRIMARY KEY,AFA INTEGER,DATUM DATE,HATARIDO DATE,UGYFELID INTEGER,FOREIGN KEY (UGYFELID) REFERENCES UGYFEL(AZONOSITO));
CREATE TABLE KIFIZETES(SZAMLASZAM INTEGER,SORSZAM INTEGER,DATUM DATE,OSSZEG NUMERIC(16,2),TIPUS VARCHAR(30),PRIMARY KEY(SZAMLASZAM,SORSZAM),FOREIGN KEY (SZAMLASZAM) REFERENCES
BESZAMLA(SZAMLASZAM));
24
CREATE TABLE BEJOVOPENZ(SZAMLASZAM INTEGER,SORSZAM INTEGER,DATUM DATE,OSSZEG NUMERIC(16,2),TIPUS VARCHAR(30),PRIMARY KEY(SZAMLASZAM,SORSZAM),FOREIGN KEY (SZAMLASZAM) REFERENCES
KISZAMLA(SZAMLASZAM));CREATE TABLE SZAMLASOR(SZAMLASZAM INTEGER,SORSZAM INTEGER,EGYSEGAR NUMERIC(16,2),MENNYISEG NUMERIC(16,2),TERMEKID INTEGER,PRIMARY KEY(SZAMLASZAM,SORSZAM),FOREIGN KEY (SZAMLASZAM) REFERENCES
KISZAMLA(SZAMLASZAM),FOREIGN KEY (TERMEKID) REFERENCES TERMEK(TERMEKID));
25
Beviteli sorrend és függőség
Ügyfél Termék
BeSzámla KiSzámla
Kifizetés BejövőPénz Számlasor
1
11
1 1
1
26
1. Melyik ügyfélnek a neve kezdődik ‘A’ betűvel?
SELECT Ugyfel.nev FROM Ugyfel WHERE Ugyfel.nev LIKE ‘A%’;
2. Melyik ügyfél nevében van benne az ‘ama’ betűkombináció?
SELECT Ugyfel.nev FROM Ugyfel WHERE Ugyfel.nev LIKE ‘%ama%’
% mindent helyettesít (mint Windowsban a *)
_ helyettesít egy karaktert (mint Windowsban a ?)
27
Melyik ügyfélhez nem tartozik számla
SELECT Ugyfel.nevFROM UgyfelWHERE Ugyfel.azonosito Not In (SELECT ugyfelID FROM
KiSzamla) And (Ugyfel.azonosito) Not In (SELECT ugyfelID FROM BeSzamla);
Melyik számlához nem tartozik számlasor (ez hiba, vagy még nem vittük be)
SELECT szamlaszamFROM KiSzamlaWHERE szamlaszam NOT IN(SELECT szamlaszam FROM Szamlasor);
Kik a beszállítók (akikhez bejövő számla tartozik)
SELECT DISTINCT Ugyfel.nevFROM Ugyfel INNER JOIN BeSzamla ON
Ugyfel.azonosito=BeSzamla.ugyfelID;
28
Melyik ügyfelek a kliensek (akikhez kimeno szamla tartozik (nem ures))
SELECT DISTINCT Ugyfel.nevFROM Ugyfel INNER JOIN KiSzamla ON Ugyfel.azonosito =
KiSzamla.ugyfelIDWHERE KiSzamla.szamlaszam IN (SELECT szamlaszam FROM Szamlasor);
Melyek azok az ügyfelek, akik egyben beszállítók és vásárlók is
SELECT DISTINCT Ugyfel.nevFROM Ugyfel INNER JOIN KiSzamla ON
Ugyfel.azonosito=KiSzamla.ugyfelIDWHERE szamlaszam IN (SELECT szamlaszam FROM Szamlasor)
ANDazonosito IN (SELECT ugyfelID FROM BeSzamla);
29
SELECT KiSzamla.szamlaszam, Szamlasor.sorszam, Termek.nev, Termek.mertekegyseg, Szamlasor.egysegar, Szamlasor.darabszam, (egysegar)*(mennyiseg) AS sorossz FROM Termek INNER JOIN (KiSzamla INNER JOIN Szamlasor ON KiSzamla.szamlaszam = Szamlasor.szamlaszam) ON Termek.termekID = Szamlasor.termekID;
Számlák a soraikkal együtt.
30
SELECT KiSzamla.szamlaszam, Szamlasor.sorszam, Termek.nev, Termek.mertekegyseg, Szamlasor.egysegar, Szamlasor.darabszam, (egysegar)*(mennyiseg) AS sorosszFROM Termek INNER JOIN (KiSzamla INNER JOIN Szamlasor ON KiSzamla.szamlaszam = Szamlasor.szamlaszam) ON Termek.termekID = Szamlasor.termekIDWHERE (((KiSzamla.szamlaszam)=[Hanyas szamla?]));
Ez a kiegészítés ACCESSben paraméterezett lekérdezést ad. A felhasználótól bekéri a számlaszámot, s csak azt az egy számlát adja meg.
31
SELECT Ugyfel.nev, KiSzamla.szamlaszam, Sum((egysegar)*(mennyiseg)*(1+KiSzamla.AFA/100)) AS osszSzamlaErtek, (Datum)+(hatarido) AS hatardatumFROM Ugyfel INNER JOIN (KiSzamla INNER JOIN Szamlasor ON KiSzamla.szamlaszam=Szamlasor.szamlaszam) ON Ugyfel.azonosito=KiSzamla.ugyfelIDGROUP BY Ugyfel.nev, KiSzamla.szamlaszam, (Datum)+(hatarido);
Megadja minden ügyfélhezt tartozó minden számla összértékét és fizetési határidejét.
32Az előző lekérdezés részleges eredménye (jelentés formájában).
33
Bejövő számláink az ügyfelekkel, összegekkel és határidőkkel
SELECT Ugyfel.nev, BeSzamla.szamlaszam, BeSzamla.osszeg, (Datum)+(hatarido) AS hatardatumFROM Ugyfel INNER JOIN BeSzamla ON Ugyfel.azonosito=BeSzamla.ugyfelID;
Az ügyfelek által vásárolt termékek, mennyiségre:
34
Ha az ügyfeleink által vásárolt termékekről szeretnénk információt fel kell vennünk a lekérdezésbe az összes táblát, amelyen keresztül a kapcsolat megoldható :
SELECT Ugyfel.nev, Termek.nev, Sum(Szamlasor.darabszam) AS SumOfdarabszamFROM Ugyfel INNER JOIN (Termek INNER JOIN (KiSzamla INNER JOIN Szamlasor ON KiSzamla.szamlaszam = Szamlasor.szamlaszam) ON Termek.termekID = Szamlasor.termekID) ON Ugyfel.azonosito = KiSzamla.ugyfelIDGROUP BY Ugyfel.nev, Termek.nev;
Az összekötések zárójelezéssel történnek, amint fentebb a színes kiemelések vannak.
35
Teljesen kifizetetlen számlákSELECT Ugyfel.nev, KiSzamla.szamlaszam, Sum((egysegar)*(mennyiseg)*KiSzamla.AFA/100) AS osszSzamlaErtekFROM Ugyfel INNER JOIN (KiSzamla INNER JOIN Szamlasor ON KiSzamla.szamlaszam=Szamlasor.szamlaszam) ON Ugyfel.azonosito=KiSzamla.ugyfelIDWHERE KiSzamla.szamlaszam NOT IN (SELECT bejovoPenz.szamlaszam FROM bejovoPenz)GROUP BY Ugyfel.nev, KiSzamla.szamlaszam;
Az alkérdés megadja azokat a számlákat, amelyekre kifizetések történtek. Ezeknek a kivonása eredményezi azon számlákat és összegeket, amelyek teljesen kifizetetlenek voltak.
36
Meg szeretnénk tudni, hogyan állnak a részlegesen fizetett számláink is.
Reszlegesen fizetett számlák és a rajtuk levő összeg
SELECT Ugyfel.nev, KiSzamla.szamlaszam, Sum((egysegar)*(mennyiseg)*KiSzamla.AFA/100) AS osszSzamlaErtekFROM Ugyfel INNER JOIN (KiSzamla INNER JOIN Szamlasor ON KiSzamla.szamlaszam=Szamlasor.szamlaszam) ON Ugyfel.azonosito=KiSzamla.ugyfelIDWHERE (((KiSzamla.szamlaszam) In (SELECT bejovoPenz.szamlaszam FROM bejovoPenz)))GROUP BY Ugyfel.nev, KiSzamla.szamlaszam;
Minden számlára az összkifizetés
SELECT bejovoPenz.szamlaszam, Sum(bejovoPenz.osszeg) AS SumOfosszegFROM bejovoPenzGROUP BY bejovoPenz.szamlaszam;
37
A két lekérdezést kombinálva kapjuk meg a tényleges állást
SELECT ReszlegesenFizetettSzamlak.nev, ReszlegesenFizetettSzamlak.szamlaszam, ReszlegesenFizetettSzamlak.osszSzamlaErtek, SzamlaraFizetes.SumOfosszeg, (osszSzamlaErtek)-(SumOfosszeg) AS kulonbsegFROM ReszlegesenFizetettSzamlak INNER JOIN SzamlaraFizetes ON ReszlegesenFizetettSzamlak.szamlaszam = SzamlaraFizetes.szamlaszam;
38
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Marosvásárhely
Csak a kifizetetlen számlák, s rajtuk levő összegek
(SELECT *FROM TeljesenKifizetetlenSzamlak)UNION (SELECT nev,szamlaszam,kulonbsegFROM ReszlegesAllasWHERE kulonbseg<>0);
Kik vannak késésben a számla-kifizetéssel
SELECT KiSzamla.szamlaszam, CsakTartozasok.osszSzamlaErtek, (Datum)+(hatarido)AS Expr1FROM KiSzamla INNER JOIN CsakTartozasok ON KiSzamla.szamlaszam=CsakTartozasok.szamlaszamWHERE Datum+hatarido>Date();
39
Sapientia - Erdélyi Magyar TudományEgyetem (EMTE) Marosvásárhely
Kik fizettek egyáltalán késveSELECT Ugyfel.nev, KiSzamla.szamlaszam, bejovoPenz.datum-KiSzamla.datum-[hatarido] AS kesesnap, bejovoPenz.osszegFROM Ugyfel INNER JOIN (KiSzamla INNER JOIN bejovoPenz ON KiSzamla.szamlaszam=bejovoPenz.szamlaszam) ON Ugyfel.azonosito=KiSzamla.ugyfelIDWHERE (((bejovoPenz.datum-KiSzamla.datum-(hatarido))>0));