background image

 

 

Wyk

ład 

4

background image

 

 

SQL – język relacyjnych 

i obiektowo-relacyjnych 

baz danych

Złożone zapytania cd.

background image

 

 

Przykładowy schemat z 

Oracle

Związek 

Emp.Sal

 z 

wartościami w tabeli 

Salgrade

:

Zarobki 

Emp.Sal

 są 

zaliczane do grupy 

Salgrade.Grade

 

takiej, że:

Emp.Sal

 należy do 

przedziału:

[Salgrade.Losal, 
Salgrade.Hisal]

background image

 

 

Tabela EMP

EMPNO ENAME     JOB       MGR HIREDATE   SAL COMM DEPTNO

----- ------- --------- ---- --------- ----- ---- ------
 7839 KING    PRESIDENT      17-NOV-81  5000          10

 7698 BLAKE   MANAGER   7839 01-MAY-81  2850          30

 7782 CLARK   MANAGER   7839 09-JUN-81  2450          10

 7566 JONES   MANAGER   7839 02-APR-81  2975          20

 7654 MARTIN  SALESMAN  7698 28-SEP-81  1250 1400     30

 7499 ALLEN   SALESMAN  7698 20-FEB-81  1600  300     30

 7844 TURNER  SALESMAN  7698 08-SEP-81  1500    0     30

 7900 JAMES   CLERK     7698 03-DEC-81   950          30

 7521 WARD    SALESMAN  7698 22-FEB-81  1250  500     30

 7902 FORD    ANALYST   7566 03-DEC-81  3000          20

 7369 SMITH   CLERK     7902 17-DEC-80   800          20

 7788 SCOTT   ANALYST   7566 09-DEC-82  3000          20

 7876 ADAMS   CLERK     7788 12-JAN-83  1100          20

 7934 MILLER  CLERK     7782 23-JAN-82  1300          10

background image

 

 

Tabele DEPT i SALGRADE

DEPT

DEPTNO DNAME       LOC

------ ----------- --------
    10 ACCOUNTING  NEW YORK
    20 RESEARCH    DALLAS
    30 SALES       CHICAGO
    40 OPERATIONS  BOSTON

SALGRADE

GRADE LOSAL HISAL

----- ----- -----
    1   700  1200
    2  1201  1400
    3  1401  2000
    4  2001  3000 
    5  3001  9999

background image

 

 

Podzapytania

Wewnątrz klauzul WHERE, HAVING i FROM, mogą 
wystąpić podzapytania, mające taką samą postać jak 
zapytania (tylko są ujęte w nawiasy). 

Podzapytanie może wystąpić jako (z reguły) prawy 
argument predykatów =, <, <=, >, >=, <>, IN, NOT IN, 
przy czym w przypadku predykatów =, <, <=, >, >=, <>, 
powinno określać jedną wartość, a w przypadku 
predykatów IN oraz NOT IN listę wartości. 

W podzapytaniu nie można używać klauzul ORDER BY. 

W podzapytaniu dostępne są nazwy kolumn wprowadzone
w głównym zapytaniu.

Podzapytanie zwykłe - zbiór wynikowych wierszy
nie zmienia się i nie zależy od wierszy
w głównym zapytaniu. 

background image

 

 

Wypisz osoby, które zarabiają najwięcej ze wszystkich 
pracowników.

Przykład

SELECT Ename, Sal
FROM Emp
WHERE 
Sal = (SELECT Max(Sal) FROM 
Emp);

ENAME    SAL

-------- ---------
KING          5000

Zapytanie to można z kolei użyć jako podzapytanie (bez 
średnika)
w warunku WHERE, wtedy kiedy trzeba przyrównać 
zarobki pracownika do maksymalnych zarobków.

Najpierw liczymy największe 

Sal

 za pomocą zapytania:

 

 SELECT Max(Sal) FROM Emp;

background image

 

 

Wypisz pracowników, którzy pracują na tym samym 
stanowisku, co pracownik o numerze 7369 i których 
zarobki są większe niż zarobki pracownika o 
numerze 7876.

 

Przykład

SELECT Ename, Job
FROM    Emp 
WHERE Job = (SELECT Job
                FROM Emp WHERE 
Empno = 7369) 
     AND Sal > (SELECT Sal
                FROM Emp WHERE 
Empno = 7876);

W klauzuli WHERE może być więcej niż jedno podzapytanie.

ENAME   JOB

------- ------
MILLER  CLERK

background image

 

 

Wypisz działy, w których pracują urzędnicy.

Przykład

SELECT Dname FROM Dept 
WHERE Deptno IN 
   (SELECT Deptno FROM Emp WHERE Job = 
'CLERK');

Gdy podzapytanie zwraca więcej niż jedną wartość zamiast operatora = stosuje się operator IN.

DNAME

------------
ACCOUNTING
RESEARCH
SALES

background image

 

 

Podzapytania a NULL

Problemy pojawiają się przy stosowaniu operatora NOT IN 
w sytuacji gdy w wyniku podzapytania jest pseudo-wartość 
NULL – o żadnej wartości nie da się stwierdzić, że jest różna od 
NULL! 

Zapytanie, które pozornie liczy wszystkich pracowników, którzy 
nie są kierownikami,

SELECT Prac.Ename

FROM Emp Prac

WHERE Prac.Empno NOT IN

              (SELECT Podw.Mgr FROM Emp 
Podw);

daje w rzeczywistości wynik będący pustą tabelą!

W Oracle wystarczy zamiast 
Podw.Mgr użyć
NVL(Podw.Mgr,0)

background image

 

 

Kwantyfikatory ALL i SOME 

(ANY)

Wyrażenie operator [ANY|SOME|ALL] [lista_wyrażeń|

(podzapytanie)]

 

    

10000 >= 

ALL

 (SELECT Sal FROM Emp)

 

“10000 większe lub równe od zarobków każdego z 

pracowników”

    

1000 >= 

SOME

 (SELECT Sal FROM Emp)

 “1000 większe lub równe od zarobków jakiegoś 

pracownika”

background image

 

 

Przykład

Wybierz nazwiska i zarobki pracowników, którzy 
zarabiają więcej od każdego pracownika z działu 
30.

SELECT Ename, Sal 
  FROM Emp
  WHERE Sal 

 

> ALL 

     (SELECT Sal  FROM Emp WHERE Deptno = 
30)

background image

 

 

Przykład

Wybierz nazwiska i zarobki pracowników, którzy 
zarabiają więcej od któregokolwiek pracownika 
zatrudnionego na stanowisku ‘SALESMAN’.

SELECT Ename, Sal 
  FROM Emp
  WHERE Sal 

 

> ANY 

     (SELECT Sal  FROM Emp WHERE Job 
=’SALESMAN' )

background image

 

 

Podzapytania skorelowane

Zbiór wyników podzapytania zależy od wartości 
występujących w wierszach w głównym zapytaniu.! 

background image

 

 

Przykład

SELECT a.Deptno, a.Ename, a.Sal
  FROM Emp a
  WHERE Sal = 
    (SELECT Max(b.Sal) 
     FROM Emp b
     WHERE b.Deptno= a.Deptno); 

 Dla każdego działu wypisz osobę, która zarabia 
najwięcej w tym dziale

.

Maksymalne zarobki w danym dziale =

 

SELECT Max(Sal) 
  FROM Emp
  WHERE Deptno=

 

<Deptno określony w 

głównym zapytaniu>

background image

 

 

Predykaty EXISTS i NOT EXISTS

 Są to predykaty sprawdzające czy podzapytanie 

daje pusty zbiór wyników czy nie, np.

EXISTS

(SELECT 'x' FROM Emp WHERE 

Deptno= 10)

“istnieje co najmniej jeden pracownik 
zatrudniony w dziale o numerze 10”. 

Dla wyniku nie jest istotne co napiszemy na liście 
SELECT 
w ramach predykatu EXISTS – najprostsza 
obliczeniowo 
jest wartość stała, taka jak 'x'.

background image

 

 

Przykład

SELECT DISTINCT Dname
  FROM Dept
  WHERE  NOT EXISTS (SELECT 'x' FROM 
Emp 
                               WHERE Emp.Deptno= 
Dept.Deptno);

Wypisz działy, w których aktualnie nikt nie jest 
zatrudniony.

DNAME

--------------
OPERATIONS

background image

 

 

Przykład

SELECT Empno, Ename, Job, Deptno
  FROM   Emp Outer
  WHERE  NOT EXISTS (SELECT 'x' 
                             FROM   Emp Inner
                            WHERE  Inner.Mgr = 
Outer.Empno);

 Za pomocą predykatu NOT EXISTS można rozwiązać 

problem wyznaczenia  wszystkich pracowników, którzy 
nie są kierownikami. Problemu tego nie udało się 
poprzednio rozwiązać za pomocą predykatu NOT IN z 
powodu występowania pseudo-wartości NULL w wyniku 
podzapytania.

background image

 

 

Korelacja w UPDATE i DELETE

 Podzapytania są częścią składową warunków w 

klauzulach WHERE i HAVING.

Zwiększ o 10% zarobki wszystkim pracownikom 
pracującym w Dallas.

UPDATE Emp 
  SET Sal = Sal * 1.1
  WHERE 
     (SELECT Loc FROM Dept 
      WHERE Emp.Deptno=Dept.Deptno) = 
'DALLAS';

background image

 

 

Użycie instrukcji SELECT w klauzuli 

FROM

Oblicz procentowy udział każdego z działów w 
liczbie pracowników i zarobkach w firmie

 SELECT a.Deptno "Dział",
               Trunc(100*a.Liczba_Prac/b.Liczba_Prac,1) AS 
"%Pracowników",
               Trunc(100*a.Suma_zarob/b.Suma_zarob,1) AS  
"%Zarobków"
FROM
  (SELECT Deptno, COUNT(*) AS Liczba_Prac, SUM(Sal) 
AS Suma_zarob 
     FROM Emp
     GROUP BY Deptno
   ) a,
  (SELECT 
        COUNT(*) AS Liczba_Prac, 
        SUM(Sal) AS Suma_zarob 
     FROM Emp
  ) b;

Dzial %Pracowników  %Zarobków

----- ------------ ----------
   10         21.4       30.1
   20         35.7       37.4
   30         42.8       32.3

background image

 

 

Klauzula AS instrukcji 

CREATE TABLE (tylko w Oracle)

Skopiuj informacje o urzędnikach i umieść je w 
nowej tabeli Urzędnicy.

CREATE TABLE Urzędnicy (Empno, 
Ename, Sal)
                                 AS SELECT Empno, 
Ename, Sal 
                                          FROM Emp
                                          WHERE Job = 
'CLERK';

Używając tej konstrukcji, na liście kolumn tabeli nie 
podajemy nazw typów danych (możemy natomiast 
określać więzy  spójności i wartości domyślne). 
System sam wyprowadza informację o typach 
danych kolumn i ich rozmiarach z wyrażeń 
występujących na liście SELECT w podzapytaniu.

background image

 

 

Instrukcja INSERT

Wstaw do pomocniczej tabeli wszystkich pracowników 
zatrudnionych w ciągu ostatnich 10 dni.

INSERT INTO Emp_new

SELECT * FROM Emp
WHERE Sysdate - Hiredate < 10;

background image

 

 

Złączenie zewnętrzne (Oracle)

Złączenie zewnętrzne rozszerza rezultat prostego 
złączenia (nazywanego wewnętrznym) o te wiersze 
z jednej z tabel, dla których w trakcie złączania nie 
znaleziono odpowiadających im wierszy w drugiej 
tabeli. Warunek złączenia podaje się w postaci 
(kolumna1 jest kolumną złączenia z pierwszej tabeli, 
kolumna2 jest kolumną złączenia z drugiej tabeli):

kolumna1 = kolumna2 (+)

lub 

kolumna1 (+) = kolumna2

background image

 

 

Przykład

SELECT Dept.Deptno, Dname, SUM(Sal)
  FROM Dept, Emp
  WHERE  Dept.Deptno = Emp.Deptno(+)
  GROUP BY Dept.Deptno, Dname;

Wypisz wszystkie działy dla każdego z nich podając 
sumaryczne zarobki zatrudnionych w nim 
pracowników.

DEPTNO    DNAME          SUM(SAL)

--------  ------------   ----------
10        ACCOUNTING      8750
20        RESEARCH

     10875

30        SALES

      9400

40        OPERATIONS

background image

 

 

Przykład c.d.

 Gdy w dziale nie ma żadnego pracownika, zbiór 

sumowanych wartości składa się z jednej wartości 
Null. Wynikiem sumowania Sum(Sal) jest pseudo-
wartość Null, reprezentowana na wydruku przez 
puste miejsce.

 Gdybyśmy chcieli w takim przypadku wypisać 

wartość 0: 

NVL(Sum(Sal),0)

background image

 

 

Przykład – to samo inaczej

Wypisz wszystkie działy, dla każdego z nich podając 
sumaryczne zarobki jego pracowników.

SELECT Dept.Deptno, Dname, 
TO_CHAR(SUM(Sal)) 
  FROM Emp, Dept
  WHERE  Emp.Deptno= Dept.Deptno
  GROUP BY Dept.Deptno, Dname
UNION
SELECT Dept.Deptno, Dname, NULL  
  FROM Dept
  WHERE NOT EXISTS (SELECT 'x' FROM Emp
                                          WHERE Emp.Deptno = 
Dept.Deptno);

DEPTNO    DNAME          To_Char(SUM(SAL))

--------  ------------   ----------
10        ACCOUNTING     8750
20        RESEARCH

     10875

30        SALES

     9400

40        OPERATIONS

background image

 

 

Drobna zmiana - typ liczbowy

Wypisz wszystkie działy, dla każdego z nich podając 
sumaryczne zarobki jego pracowników.

SELECT Dept.Deptno, Dname, SUM(Sal)
   FROM Emp, Dept
  WHERE  Emp.Deptno= Dept.Deptno
  GROUP BY Dept.Deptno, Dname
UNION
SELECT Dept.Deptno, Dname, 0  
  FROM Dept
  WHERE NOT EXISTS (SELECT 'x' FROM Emp
                                          WHERE Emp.Deptno = 
Dept.Deptno);

DEPTNO    DNAME          SUM(SAL)

--------  ------------   ----------
10        ACCOUNTING     8750
20        RESEARCH

     10875

30        SALES

     9400

40        OPERATIONS     0

background image

 

 

Wbudowane operatory złączeń 

(Standard)

  Złączenie tabel można określać bezpośrednio w 
klauzuli 
FROM (T, U oznaczają tabele):

  Złączenie krzyżowe 

T CROSS JOIN U

 - iloczyn 

kartezjański - wszystkie kombinacje wierszy.  

  Złączenie wewnętrzne 

T INNER JOIN U

 - złączenie 

wierszy obu tabel względem kolumn o tych samych 
nazwach.  

  Złączenie zewnętrzne

   a.  lewostronne 

T LEFT OUTER JOIN U

   b.  prawostronne 

T RIGHT OUTER JOIN

 

U

   c.  pełne 

T FULL OUTER JOIN U

 (suma wyników

 złączenia zewnętrznego lewostronnego i 
prawostronnego).


Document Outline