Bazy Danych1 secret id 81733 Nieznany (2)

background image

1

Bazy Danych

Prowadzący:
Andrzej Z. Sikorski

Podręcznik:
Chris J. Date Wprowadzenie do Systemów Baz Danych
Rozdziały 8, 10 (dodatkowo 11)

Oprogramowanie:
MS SQL Server

background image

2

S#

P#

J#

QTY

S1

P1

J1

200

S1

P1

J4

700

S2

P3

J1

400

S2

P3

J2

200

S2

P3

J3

200

S2

P3

J4

500

S2

P3

J5

600

S2

P3

J6

400

S2

P3

J7

800

S2

P5

J2

100

S3

P3

J1

200

S3

P4

J2

500

S4

P6

J3

300

S4

P6

J7

300

S5

P2

J2

200

S5

P2

J4

100

S5

P5

J5

500

S5

P5

J7

100

S5

P6

J2

200

S5

P1

J4

100

S5

P3

J4

200

S5

P4

J4

800

S5

P5

J4

400

S5

P6

J4

500

S#

SNAME

STATUS

CITY

S1

Smith

20 London

S2

Jones

10 Paris

S3

Blake

30 Paris

S4

Clark

20 London

S5

Adams

30 Athens

P#

PNAME

COLOR

WEIGHT

CITY

P1

Nut

Red

12.00

London

P2

Bold

Green

17.00

Paris

P3

Screw

Blue

17.00

Rome

P4

Screw

Red

14.00

London

P5

Cam

Blue

12.00

Paris

P6

Cog

Red

19.00

London

J#

JNAME

CITY

J1

Sorter

Paris

J2

Dispay

Rome

J3

OCR

Athens

J4

Console

Athens

J5

RAID

London

J6

EDS

Oslo

J7

Tape

London

Chris Date: Dostawcy-Cz

ęś

ci-Projekty

background image

3

Terminologia

S

(SUPPLIER) Dostawca

P

(PART) Część

J

(JOB) Projekt, Zadanie, Przedsięwzięcie

SPJ SUPPLIER- PART- JOB

QTY (Quantity) ilość

background image

4

CREATE TABLE [J] (

[J#] [varchar] (10) COLLATE Latin1_General_CI_AS NOT NULL ,
[JNAME] [varchar] (100) COLLATE Latin1_General_CI_AS NULL ,
[CITY] [varchar] (100) COLLATE Latin1_General_CI_AS NULL ,

PRIMARY KEY CLUSTERED

(

[J#]

) ON [PRIMARY]

) ON [PRIMARY]

CREATE TABLE J(

J# varchar(10) NOT NULL PRIMARY KEY,
JNAME varchar(100),

CITY varchar(100))

Tabelka projektów

background image

5

CREATE TABLE P (P# varchar(10) NOT NULL PRIMARY KEY,

PNAME

varchar(100),

COLOR

varchar(100),

WEIGHT

numeric(5,2),

CITY

varchar(100))

CREATE TABLE S (S# varchar(10) NOT NULL PRIMARY KEY,

SNAME varchar(100),

STATUS

int,

CITY

varchar(100))

Tabelki cz

ęś

ci i dostawców

background image

6

Dostawy

CREATE TABLE SPJ (

S# varchar(10) references S( S#),
P# varchar(10) references P( P# ),
J# varchar(10) references J( J# ),

QTY int

)

background image

7

Ogólna posta

ć

polecenia CREATE TABLE

CREATE TABLE

[ database_name.[ owner ] . | owner. ] table_name
( { < column_definition >

| column_name AS computed_column_expression
| < table_constraint > ::= [ CONSTRAINT constraint_name ] }

| [ { PRIMARY KEY | UNIQUE } [ ,...n ]

)

[ ON { filegroup | DEFAULT } ]
[ TEXTIMAGE_ON { filegroup | DEFAULT } ]

background image

8

Model O-Z bazy Dostawcy-cz

ęś

ci-projekty

J

J#
JNAME
CITY

varchar(10)
varchar(100)
varchar(100)

<pk>

P

P#
PNAME
COLOR
WEIGHT
CITY

varchar(10)
varchar(100)
varchar(100)
numeric(5,2)
varchar(100)

<pk>

S

S#
SNAME
STATUS
CITY

varchar(10)
varchar(100)
int
varchar(100)

<pk>

SPJ

S#
P#
J#
QTY

varchar(10)
varchar(10)
varchar(10)
int

<fk3>
<fk2>
<fk1>

background image

9

Najprostsze zapytanie

select * from S

rezultat

S#

SNAME

STATUS

CITY

S1

Smith

20 London

S2

Jones

10 Paris

S3

Blake

30 Paris

S4

Clark

20 London

S5

Adams

30 Athens

select * from (select * from S) sx

background image

10

Proste zapytania 1

select * from S
where status >10

rezultat

select * from (select * from S where status >10) sx

select * from (select * from S) sx
where status >10

S#

SNAME

STATUS

CITY

S1

Smith

20 London

S3

Blake

30 Paris

S4

Clark

20 London

S5

Adams

30 Athens

background image

11

Proste zapytania 2

select S# from S

rezultat

select S# from (select * from S) sx

select * from (select S# from S) sx

S#
S1
S2
S3
S4
S5

background image

12

Proste zapytania 3

select S# from S
where status >10

rezultat

select S# from (select * from S where status >10) sx

S#
S1
S3
S4
S5

background image

13

select P.COLOR,P.CITY
from P
where

not P.CITY='Paris' and
P.Weight>10

COLOR

CITY

Red

London

Blue

Rome

Red

London

Red

London

Podaj miasto i kolor części nie pochodzących z Paryża o wadze
większej niż 10.

Proste zapytania 4

Zadanie: za pomocą zapytań w klauzuli from podać postacie
równoważne! Ile jest takich postaci?

background image

14

select P.COLOR,P.CITY from P //tylko COLOR i CITY

select * from P

//wszystkie kolumny

//znowu wszystkie – wymienione explicite
select P.P#,P.PNAME,P.COLOR,P.WEIGHT,P.CITY from P

select COLOR,CITY from P //tylko COLOR i CITY
//nazwy jednoznaczne można opuścić tabelkę

Projekcja – wybór podzbioru kolumn

background image

15

select * from P

//wszystkie wiersze

//waga większa niż 15 uncji (przykład amerykański)
select * from P where weight>15

Selekcja – wybór podzbioru wierszy

//waga >15 i miasto pochodzenia Paryż
select * from P where weight>15 and City=‘Paris’

background image

16

select count(*) from P
rezultat 6
//Grupę stanowi cała tabelka!

Grupowanie 1

1.

2.

select avg(WEIGHT) from P
rezultat 15.166666

3.

select count(*) from P
where City=‘London’
rezultat 3

4.

select count(*),City from P

5.

select count(*),max(City) from P

background image

17

select count(*) from P
group by City
//Grupowanie wg. miasta

Grupowanie 2

1.

3
2
1

select count(*),City from P
group by City
//można użyć agregatów i pól
//grupujących

2.

CITY

3 London
2 Paris
1 Rome

select count(*) as Count,City from P
group by City
//nazwane pole agregatu

3.

background image

18

select count(*) as count,City
from P
where weight>12
group by City
//warunek selekcji

Grupowanie 3

1.

select count(*) as count,City
from P
where weight>12
group by City
having count(*)>1

2.

count

CITY

2 London
1 Paris
1 Rome

count

CITY

2 London

background image

19

Grupowanie 4

select * from
(select
count(*) as c,City
from P
where weight>12
group by City) px
where c>1
//where zamiast having –dzięki użyciu zapytania we from

1.

2.

c

CITY

2 London

//wyznaczyć największą średnią wagę wg. miast
select max(a) from
(select avg(weight) a from P
group by City) px
//Częsty błąd max(avg(x))

background image

20

Przykład

Znaleźć miasto dla którego średnia waga części jest największa!

select City from p
group by City
having avg(weight)=
(select max(a) from
(select avg(weight) a from P
group by City) px)

select City from p
group by City
having avg(weight)=
„największa wartość”

1.

2.

background image

21

Zagnie

ż

d

ż

anie (wst

ę

p)

select City from p
group by City
having avg(weight)=
(select max(a) from
(select avg(weight) a from P
group by City) px)

1) Przykład z p.19 tzw. FROM LISTEN SUBQUERY
2) Zapytanie skalarne - wynik pojedyncza wartość jeden wiersz

jedna kolumna używana zamiast stałej w selekcji

(jedna kolumna w select i
grupowanie bez group by)

background image

22

ą

czenie 1(join)

1.

select count(*) from SPJ

24

select count(*) from P

6

select count(*) from P,SPJ

6*24=144

Iloczyn kartezjański (każdy z każdym)

2.

Podzbiór iloczynu kartezjańskiego bo z selekcją. Dwie notacje

select * from P,SPJ where P.P#=SPJ.P#

select * from P join SPJ on P.P#=SPJ.P#

background image

23

ą

czenie 2

3.

select count(*) from P,SPJ,S

6*24*5=720

Iloczyn kartezjański trzech tabelek

4.

Notacja where

select * from P,SPJ,S where

P.P#=SPJ.P# and
S.S#=SPJ.S#

select * from P join SPJ on P.P#=SPJ.P# join

S on S.S#=SPJ.S#

5.

Ta „druga” notacja Samodzielnie opracować przykład dla czterech
tabelek!

background image

24

ą

czenie 2a

select count(*) from P,SPJ,S

6*24*5=720

select count(*) from P

6

select count(*) from SPJ

24

select count(*) from S

5

Zadanie: ile będzie wierszy w wyniku?

select * from P,SPJ,S where

P.P#=SPJ.P#

Iloczyn kartezjański trzech tabelek

background image

25

ą

czenie 2b

ile teraz będzie wierszy w wyniku?

select * from P,SPJ,S where

S.S#=SPJ.S#

Już prościzna.

background image

26

ą

czenie 3

6.

select * from P cross join SPJ

Iloczyn kartezjański dla notacji z użyciem join

Po co?

select * from P cross join SPJ join S
on SPJ.S#=S.S#

Jest odpowiednikiem zapytania:

select * from P,SPJ,S where S.S#=SPJ.S#

Lub równoważnie:

select * from P,SPJ join S on SPJ.S#=S.S#

background image

27

Zadanie 1. zapisać wykorzystując notację cross join

select * from P,SPJ,S where

P.P#=SPJ.P#

ą

czenie 3a

Zadanie 2. zapisać powyższe zapytanie na wszystkie możliwe sposoby.
Wykorzystać notację where oraz join. Można też skorzystać (premiowane)
From Listen Subquery.

background image

28

select

*

from

SPJ

,

P

,

S

where

P

.

P#

=

SPJ

.

P#

select

*

from

P

,

SPJ

cross join

S

where

P

.

P#

=

SPJ

.

P#

select

*

from

P

join

SPJ

on

P

.

P#

=

SPJ

.

P#

cross join

S

select

*

from

P

join

SPJ

on

P

.

P#

=

SPJ

.

P#

,

S

ą

czenie 3b

Zadanie 2. Rozwiązanie. Muszą być 4 możliwości (dlaczego?)

From listen subquery

select

*

from

S

,

(

select

P

.

P#

from

SPJ

join

P

on

P

.

P#

=

SPJ

.

P#

)

t

Dlaczego nie może być tutaj *?

Wskazówka.

background image

29

ą

czenie 4 (przykłady)

select CITY,QTY from SPJ join J on J.J#=SPJ.J#

Zadanie wymagające użycia złączenia, wypisać wielkości dostawy wraz
z miastami projektów, których dotyczyły.

Złączenie + projekcja

Pary: miasto składowania – miasto projektu dla dostaw.

select distinct P.CITY,J.CITY from P,J,SPJ
where SPJ.J#=J.J# and SPJ.P#=P.P#

background image

30

ą

czenie 5 (przykłady c.d.)

Baza Northwind: pary pracowników z tego samego miasta:

select e1.LastName,e2.LastName,e1.City
from Employees e1,Employees e2
where
e1.City=e2.City and
e1.LastName<e2.LastName

Podobne, Baza SPJ: pary części składowanych w tych samych
miastach.

select p1.P#,p2.P# from P p1 join P p2 on p1.City=p2.City

background image

31

ą

czenie 6 (przykłady c.d.)

P1

P1

P1

P4

P1

P6

P2

P2

P2

P5

P3

P3

P4

P1

P4

P4

P4

P6

P5

P2

P5

P5

P6

P1

P6

P4

P6

P6

Element w parze z „sobą”

powtórki

Dlatego należy dodać:
...
and p1.P#<p2.P#

background image

32

ą

czenie 7 MS SQL

< joined_table > ::=

< table_source > < join_type > < table_source > ON

< search_condition >

| < table_source > CROSS JOIN < table_source >
| [ ( ] < joined_table > [ ) ]

< join_type > ::=

[ INNER | { { LEFT | RIGHT | FULL } [ OUTER] } ]
[ < join_hint > ]
JOIN

Przykładowe złączenie (wykorzystano wszystkie możliwości składniowe):

select count(*) from S inner loop join SPJ on S.S#<>SPJ.S#
Wynik 24*4=96 (dlaczego?)

background image

33

Wszystko razem

Wypisać nazwy części z Londynu, których sumaryczne dostawy przekroczyły 1000:

select P.P#,max(PNAME) from P,SPJ
where

SPJ.P#=P.P# and
CITY='London'

group by P.P#
having sum(QTY)>1000

Selekcja, Projekcja,Grupowanie, Złączenie

background image

34

Chris J. Date 8.3.5

select distinct S.CITY as SCITY, P.CITY as PCITY
from S join SPJ on S.S#=SPJ.S# join P on P.P#=SPJ.P#

MS SQL

select distinct S.CITY as SCITY, P.CITY as PCITY
from S join SPJ using S# join P using P#

Date str.268, podaj pary nazw miast, że dostawca z pierwszego miasta
Dostarcza część składowaną w drugim (SCITY,PCITY)

background image

35

Chris J. Date 8.3.6

Date str.268, Numery par dostawców pochodzących z tego samego miasta

select First.S# as SA, Second.S# as SB from
S First,S Second
where
First.City=Second.City
and
First.S#<Second.S#

W tym przypadku można uruchomić pod MS SQL bez zmian!
Co jeśli pominąć drugi warunek klauzuli where?

background image

36

Chris J. Date 8.3.7

Date str.268, Podaj liczbę dostawców!

select count(*) as N from S

Date str.268, Podaj liczbę miast w których rezydują dostawcy!

select count(CITY) as N from S

select count(distinct CITY) as N from S

background image

37

Chris J. Date c.d.

8.3.8 Podać maksymalną i minimalna liczbę części P2 na zamówieniu!

select max(QTY) as MAXQ,min(QTY) as MINQ from SPJ
where P#=‘P2’

8.3.9 Podać numery części wraz z odpowiednimi wielkościami dostaw!

select P#,sum(QTY) as TOTQTY from SPJ
group by P#

Numery części wraz z liczbami zamówień?
- ze średnią wielkością zamówienia?

background image

38

Chris J. Date c.d.

8.3.9 Alternatywne rozwiązanie.

select P.P#,
(select sum(QTY) from SPJ where SPJ.P#=P.P#) as TOTQTY
from P

8.3.10 Podaj numery części dostarczanych przez więcej niż jednego dostawcę!

select P# from SPJ
group by P#
having count(distinct S#)>1

Termin: Select Listen Subquery

background image

39

Chris J. Date (klauzula in)

8.3.11 Nazwy dostawców dostarczających część P2!

select distinct SNAME from S
where
S# in (select S# from SPJ where SPJ.P#='P2')

1)

Wprowadzono operator in w warunku.

2)

Jaka jest „złożoność obliczeniowa” tego zapytania? Przeszukiwanie wyniku
select S# from SPJ where SPJ.P#='P2' nie może już korzystać z klucza!

3)

Poprawne rozwiązanie na następnej stronie!

4)

Zagnieżdżanie (użycie nawiasów i podzapytań) jest tak ważne, że będzie
oddzielny wykład.

background image

40

Chris J. Date (klauzula exists)

8.3.11 Nazwy dostawców dostarczających część P2! Alternatywne rozwiązania.

select SNAME from S
where
exists( select * from SPJ where S.S#=SPJ.S# and SPJ.P#='P2')

select max(SNAME) from SPJ,S
where
P#='P2' and
SPJ.S#=S.S#
group by S.S#

Nowy typ warunku: exists.
Prawdopodobnie najbardziej efektywne rozwiązanie:

Logicznie, max można by opuścić ale...

background image

41

Chris J. Date 8.3.11,13

8.3.11 Ostatni wariant: distinct zamiast max oraz grupowania.

select distinct SNAME from SPJ,S
where
P#='P2' and
SPJ.S#=S.S#

8.3.13 Podaj dostawców mających status mniejszy od aktualnie największego!

select S# from S
where
STATUS<(select max(STATUS) from S)

Dla zabawy (ale się przyda) bez max. Tj. istnieje o wyższym statusie)

background image

42

8.3.12 – in kontra join

select distinct SNAME from S
where S# in
(select SPJ.S# from SPJ

where SPJ.P# in (select P# from P where Color='Red'))

A efektywniej byłoby:

select distinct SNAME from SPJ,P,S
where

SPJ.P#=P.P# and
SPJ.S#=S.S# and
Color='Red'

8.3.12 Podać nazwy dostawców co najmniej jednej czerwonej części!

background image

43

8.3.15 – exists w nowej postaci

Wersja z operatorem in samodzielnie.

8.3.12 Podać nazwy dostawców nie dostarczających P2. Wariant z exists.

select SNAME from S
where
not
exists( select * from SPJ where S.S#=SPJ.S# and SPJ.P#='P2')

background image

44

select

S#

from

S

where

not exists

(

select

*

from

SPJ

where

P#

=

'P2'

and

SPJ

.

S#

=

S

.

S#

)

select

S#

from

S

where

not exists

(

select

*

from

SPJ

where

P#

=

'P3'

and

SPJ

.

S#

=

S

.

S#

)

Dostawcy nie sprzedający określonej części (1)

Powinno działać zawsze

background image

45

Dostawcy nie sprzedający określonej części (1a)

Tu będzie kiedyś slajd 1a o zanegowaniu złączenia.
Nie można po prostu zanegować warunku ci co kupują różne od p2
to nie są ci sami co nie kupują p2

background image

46

Dostawcy nie sprzedający określonej części (1a)

select distinct

CompanyName

from

Customers c

,

Orders o

,

[Order Details] od

,

Products p

,

Categories c1

where

c

.

CustomerID

=

o

.

CustomerID

and

o

.

OrderID

=

od

.

OrderID

and

od

.

ProductID

=

p

.

ProductID

and

p

.

CategoryID

=

c1

.

CategoryID

and

c1

.

CategoryName

=

'Beverages'

Zadanie lab3-2g
Optymalny zapis – wyszukiwanie po kluczach zawsze jest szybsze niż
podzapytania.
Samodzielnie: zapisać z użyciem in albo exists

background image

47

select distinct

CompanyName

from

Customers c

where

not

exists

(

select

*

from

Orders o

,

[Order Details] od

,

Products p

,

Categories c1

where

c

.

CustomerID

=

o

.

CustomerID

and

o

.

OrderID

=

od

.

OrderID

and

od

.

ProductID

=

p

.

ProductID

and

p

.

CategoryID

=

c1

.

CategoryID

and

c1

.

CategoryName

=

'Beverages'

)

Dostawcy nie sprzedający określonej części (1b)

Zastąpienie join przez exists , potem już proste dodać

NOT

Jak tego uniknąć i zanegować złączenie?

background image

48

Dostawcy nie sprzedający określonej części (2)

Trochę o popełnianych błędach. Część P2 sprzedaje tylko S5

select

S#

from

S

where

S#

<>(

select distinct

S#

from

SPJ

where

P#

=

'P3'

)

Co się stanie dla części sprzedawanych przez większą liczbę
dostawców?

Niby drobiazg

select

S#

from

S

where

S#

<>(

select distinct

S#

from

SPJ

where

P#

=

'P2'

)

background image

49

Dostawcy nie sprzedający określonej części (3)

Ten sam błąd (założenie że tylko jeden sprzedaje) ale inny skutek.

select

S

.

S#

from

S

, (

select distinct

S#

from

SPJ

where

P#

=

'P2'

)

spj1

where

spj1

.

S#

<>

S

.

S#

Załóżmy, że jest więcej sprzedających (P3) – są to S2,S3,S5
S

X

{S2,S3,S5} (takie, że S.S#<>SPJ1.S#)

select

S

.

S#

from

S

, (

select distinct

S#

from

SPJ

where

P#

=

'P3'

)

spj1

where

spj1

.

S#

<>

S

.

S#

background image

50

Dostawcy nie sprzedający określonej części (4)

S

spj1

S1

S2

S2

S2

S3

S2

S4

S2

S5

S2

S1

S3

S2

S3

S3

S3

S4

S3

S5

S3

select

S

.

S#

from

S

,

(

select distinct

S#

from

SPJ

where

P#

=

'P3'

)

spj1

where

spj1

.

S#

<>

S

.

S#

Zgodnie z oczekiwaniami
usunięte

Niestety!

Błąd dużo gorszy, bo tamten
powodował komunikat

Już nawet nie trzeba zaglądać do par z S5!

background image

51

Dostawcy nie sprzedający określonej części (4a)

select

S

.

S#

from

S

,

(

select distinct

S#

from

SPJ

where

P#

=

'P2'

)

spj1

where

spj1

.

S#

<>

S

.

S#

S

spj1

S1

S5

S2

S5

S3

S5

S4

S5

S5

S5

Teraz OK ale tylko dlatego, że spj1 ma jeden
element!
Liczona ma być różnica zbiorów.

background image

52

Dostawcy nie sprzedający określonej części (4b)

Będzie dobrze jeśli:

select

S#

from

S

where

S#

not in

(

select

S#

from

SPJ

where

P#

=

'p3'

)

select

S#

from

S

except

select

S#

from

SPJ

where

P#

=

'p3'

lub

Ciągle 2 podzapytania, chcemy zrobić to jednym. (in, exist, except)

background image

53

Dostawcy nie sprzedający określonej części (5)

O pewnej „wymuszonej” na prowadzącym ocenie 5.0.

select

S#

from

S

where

(

select

COUNT

(*)

from

SPJ

where

S

.

S#

=

SPJ

.

S#

and

P#

=

'P3'

)=

0

Niby miało być bez exists oraz in ale exists to po prostu:

select

S#

from

S

where

(

select

COUNT

(*)

from

SPJ

where

S

.

S#

=

SPJ

.

S#

and

P#

=

'P3'

)>

0

select

S#

from

S

where

exists(

select

*

from

SPJ

where

S

.

S#

=

SPJ

.

S#

and

P#

=

'P3'

)

background image

54

Dostawcy nie sprzedający określonej części (6)

select

S

.

S#

,

P#

from

S

left outer join

SPJ

on

SPJ

.

P#

=

'P3'

and

SPJ

.

S#

=

S

.

S#

S1

NULL

S2

P3

S2

P3

S2

P3

S2

P3

S2

P3

S2

P3

S2

P3

S3

P3

S4

NULL

S5

P3

W kolumnie dostawców znajdą
się też wszyscy również ci co nie
dostarczają – wartością NULL

Szukany zbiór dostawców
wystarczy dodać warunek.

background image

55

Dostawcy nie sprzedający określonej części (7)

Pojęcie „naukowe” (czyt. nałkowe): left anti join

select

S

.

S#

from

S

left outer join

SPJ

on

SPJ

.

P#

=

'P3'

and

SPJ

.

S#

=

S

.

S#

where

SPJ

.

P#

is null

1) Złączenie i antyzłączenie. Lewe i prawe bo nieprzemienne.
2) Zadanie można też sformułować jako różnicę zbiorów:

S-(ci co dostarczają P3)

3) Nowe słowo kluczowe is nie ma czegoś takiego NULL=NULL

czy dwie „próżnie” są sobie równe? Dwie lokacje są puste czy
zawierają to samo jeśli nic nie zawierają? (filozofia☺)

background image

56

Dostawcy nie sprzedający określonej części (8)

Operator różnicy except (i na razie koniec z tym zadaniem)
wróci jeszcze z bazą Northwind i napojami bezalkoholowymi
(i.e. beverages)

select

S#

from

S

except

select

S#

from

SPJ

where

P#

=

'P3'

1) Tylko pewna sztuczka notacyjna tzw. lukier (syntactic sugar)
2) W praktyce sprowadza się do operatora not in podobnie jak

count()=0 i not exists

3) Technika z outer join warta zapamiętania ponieważ serwery

SQL są zoptymalizowane pod kątem złączeń

4) Except też warte – bo będzie w dzieleniu relacyjnym,
5) Tak naprawdę wydajny SQL optymalizuje anti join

background image

57

Podwójna agregacja (1)

select

MAX

(

Qty

)

from

(

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

)

t

select

Min

(

Qty

)

from

(

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

)

t

Wyznaczyć ekstremalne wartości sumaryczne zamówień
(sumy order details zgrupowane dla OrderID)

background image

58

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

Podwójna agregacja (1a)

jest jakaś największa wartość

background image

59

Podwójna agregacja (1b)

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

order by

1

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

order by

1

desc

select

top

1

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

order by

1

desc

background image

60

Podwójna agregacja (2)

select

MAX

(

Qty

)

from

(

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

)

t

Wykorzystanie FROM LISTEN SUBQUERY.

Kiedyś tylko w Oracle, w innych SQL konieczne zdefiniowane
„pomocniczej tabelki” przechowującej sumy.

Wykonanie następnej agregacji (max/min) na pomocniczym
zbiorze wynikowym.

Wyższa szkoła jazdy (master class☺) – zrobić to bez zbioru
pomocniczego (zaraz będzie).

Zagnieżdżenie (zapisać na „boku” nazwać t)
i wykonać select max(Qty) from t

background image

61

Podwójna agregacja (3)

with

t

as

(

select

SUM

(

Quantity

*

UnitPrice

)

Qty

from

[Order Details]

group by

OrderID

)

select

MAX

(

qty

)

from

t

Fajne tylko chyba pojawiło się jeszcze później niż FROM LISTEN.

create view

t

as

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

Fajne tylko zostaje t czasem nie wiadomo po co.

background image

62

Podwójna agregacja (3a)

Tymczasowy obiekt pomocniczy.

Były już zmienne i polecenie declare (dekompozycja złożonego
zapytania na zapytania prostsze)

Zmienna może również być typu tablicowego i.e. przechowywać
tymczasową tablicę

declare

@t

table

(

qty

float

);

insert

@t

select

SUM

(

Quantity

*

UnitPrice

)

as

Qty

from

[Order Details]

group by

OrderID

select

MAX

(

qty

)

from

@t

Jest jeszcze jedna możliwość tworzenia obiektów pom. Ale o tym
kiedy indziej

background image

63

Podwójna agregacja (4)

Możliwe rozwiązanie bez obiektów pomocniczych oraz bez from
listen.

Przedefiniowanie pytania – technika nie jest uniwersalna.

Wartość największa

nie istnieje taka sumaryczna wartość która

jest większa

Dla wartości najmniejszej analogicznie

background image

64

Podwójna agregacja (4a)

select distinct

OrderID

from

[Order Details] od1

where

not exists

(

select

*

from

[Order Details] od2

where

(

select

SUM

(

Quantity

*

UnitPrice

)

from

[Order Details] od3

where

od3

.

OrderID

=

od2

.

OrderID

)>

(

select

SUM

(

Quantity

*

UnitPrice

)

from

[Order Details] od3

where

od3

.

OrderID

=

od1

.

OrderID

)

)

background image

65

Zadania lab 3-4c,d (1)

4. Baza Northwind. Agregacja i złączenia (wstęp)

Zwróćmy uwagę, że warunki z zadań 3B-3E mogłyby
dotyczyć sumarycznych dostaw (suma QTY ze
wszystkich odpowiednich wierszy tabeli SPJ). W takim
wypadku należy się posłużyć złączeniem i agregacją.

C. Klienci (CompanyName) wraz z wartością zamówień
D. Klienci (CompanyName) o wartości zamówień większej

od średniej

background image

66

Zadania lab 3-4c,d (2)

Drobna modyfikacja: zamiast klientów kategorie (logika ta sama
– struktura zapytania też – dlaczego?)

selects

sum

(

Quantity

*

Products

.

UnitPrice

),

CategoryID

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

group by

CategoryID

background image

67

Zadania lab 3-4c,d (3)

Nazwa zamiast CategoryID (3 sposoby):

Będą pokazane 3 techniki:
-zagnieżdżenie w klauzuli select
-sztuczna agregacja (tj. użycie funkcji agregującej tylko w celu
zapewnienia poprawności składniowej)
-dodatkowy argument w group by

background image

68

Zadania lab 3-4c,d (3)

select

sum

(

Quantity

*

Products

.

UnitPrice

),

(

select

CategoryName

from

Categories

where

Categories

.

CategoryID

=

Products

.

CategoryID

)

CategoryName

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

group by

CategoryID

Nazwa zamiast CategoryID (3 sposoby):

select

sum

(

Quantity

*

Products

.

UnitPrice

),

MAX

(

CategoryName

)

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

join

Categories

on

Categories

.

CategoryID

=

Products

.

CategoryID

group by

Products

.

CategoryID

background image

69

Zadania lab 3-4c,d (4)

select

sum

(

Quantity

*

Products

.

UnitPrice

),

CategoryName

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

join

Categories

on

Categories

.

CategoryID

=

Products

.

CategoryID

group by

Products

.

CategoryID,CategoryName

„Sztuczne” grupowanie, zamiast
„sztucznej” agregacji

background image

70

Zadania lab 3-4c,d (5)

select

sum

(

Quantity

*

Products

.

UnitPrice

),

MAX

(

CategoryName

)

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

join

Categories

on

Categories

.

CategoryID

=

Products

.

CategoryID

group by

Products

.

CategoryID

having

sum

(

Quantity

*

Products

.

UnitPrice

)>”

ś

rednia warto

ść

obrotów”

Zadanie 4d (zmodyfikowane, bo dla kategorii):

select

avg

(

total

)

from

(

select

sum

(

Quantity

*

Products

.

UnitPrice

)

total

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

group by

CategoryID

)

t

background image

71

Zadania lab 3-4c,d (6)

Połączenie dwóch zapytań – rozwinięcie lub zmienna pomocnicza.
Złożone (complex) ale nie trudne – poskładane z klocków☺

select

max

(

CategoryName

)

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

join

Categories

on

Categories

.

CategoryID

=

Products

.

CategoryID

group by

Products

.

CategoryID

having

sum

(

Quantity

*

Products

.

UnitPrice

)>

(

select

avg

(

total

)

from

(

select

sum

(

Quantity

*

Products

.

UnitPrice

)

total

from

[Order Details]

join

Products

on

Products

.

ProductID

=

[Order Details]

.

ProductID

group by

CategoryID

)

t

)

background image

72

Typ zapyta

ń

„dla ka

ż

dego” 1 (forall)

8.3.16 Dostawcy sprzedający wszystkie części.

Wersja łatwiejsza. Porównanie liczb części dla dostawców.

select S# from S where
(select count(distinct P#) from SPJ

where SPJ.S#=S.S#)=

(select count(*) from P)

W zwolnionym tempie! –slow motion replay

1) Liczba produktów w ogóle sprzedawanych.

select count(*) from P

Wynik: 6

background image

73

Typ zapyta

ń

„dla ka

ż

dego” 2

8.3.16 Dostawcy sprzedający wszystkie części slow motion. c.d.

select S#,count(distinct P#) from SPJ
group by S#

Wynik:

S1

1

S2

2

S3

2

S4

1

S5

6

Łopatologicznie więc dostajemy:

select S# from SPJ
group by S#
having count(distinct P#)=(select count(*) from P)

background image

74

Typ zapyta

ń

„dla ka

ż

dego” 3

8.3.16 Dostawcy sprzedający wszystkie części slow motion. c.d.
Pamiętamy, że grupowanie można zastąpić przez zagnieżdżone zapytanie.

select S#,

(select count(distinct P#) from SPJ where SPJ.S#=S.S#) as ILE

from S

Wynik ten sam – teraz kolumnę ile można porównać w klauzuli where.

C.J.Date na temat rozwiązań opartych na liczeniu wierszy:
1)

Oparte na założeniu, że jest spełnione połączenie oparte na kluczu. Tj. nie
ma takich wierszy SPJ, że wartości w kol. P# nie ma w tabelce P.

2)

Nie wszystkie produkty umożliwiają użycie zagnieżdżonych zap. (już nie
jest to prawda)

3)

W wielu zadaniach typu „dla każdego” technika ta nie wystarcza!

background image

75

Typ zapyta

ń

„dla ka

ż

dego” 4

select S# from S
where

not exists (

select * from P

where
not exists
(select * from SPJ where

SPJ.S#=S.S# and
SPJ.P#=P.P#))

Skoro dostarcza wszystko to nie ma takiej części której by nie dostarczał.

Teraz to samo w zwolnionym tempie

background image

76

Typ zapyta

ń

„dla ka

ż

dego” 5

select S# from S
where

not exists (

„część której S# nie dostarcza ”)

Zapytanie ma znaleźć dostawców więc tabelka S.

Dla danego S# szukamy części których on nie dostarcza!

select P# from P
where
not exists
(„pozycja z SPJ dla częsci P# i danego S#”)

background image

77

Typ zapyta

ń

„dla ka

ż

dego” 6

select P# from P
where

not exists (select * from SPJ
where SPJ.P#=P.P# and

SPJ.S#='S2')

Znaleźć części których S2 nie dostarcza!

Podsumowując:

)

(

)

(

x

x

x

x

ϕ

ϕ

¬

¬

select * from S
where forall(x,

ϕ

(x))

select * from S
where not exists(x, not

ϕ

(x))

background image

78

select * from Customers c
where
not exists
(
select * from
Employees e
where
exists

(select * from Orders o

where o.EmployeeID=e.EmployeeID and

o.CustomerID=c.CustomerID)

and

exists (select * from Products where

exists (select * from Orders o,[Order Details] od

where o.OrderID=od.OrderID and

o.EmployeeID=e.EmployeeID and
od.ProductID=Products.ProductID)

and

not exists(select * from Orders o,[Order Details] od

where o.OrderID=od.OrderID and

o.EmployeeID=e.EmployeeID and
c.CustomerID=o.CustomerID and

od.ProductID=Products.ProductID )

))

Teaser/Challenge

background image

79

Rozbudowany przykład

select P.P#,

'Waga w gramach' as text1,
P.weight*454 as GMWT,
P.COLOR,
'Maksymalna ilość' as text2,
max(SPJ.QTY) as MQTY

from P,SPJ
where P.P#=SPJ.P# and

P.COLOR in ('Red','Blue') and
SPJ.QTY>200

group by P.P#,P.WEIGHT,P.COLOR
having sum(SPJ.QTY)>1000

background image

80

ą

czenie zewn

ę

trzne

select P.P#,QTY
from p,spj
where
spj.p#=*p.p# and spj.qty>500

select P.P#,QTY from
p left outer join (select P#,QTY from SPJ

where QTY>500) P1

on P1.P#=P.P#

background image

81

Proste aplikacje klienckie

Odwieczny problem: klienci, klienty, agenci, agenty, jest piloci –piloty

Te same
parametry

background image

82

try

{

com.microsoft.sqlserver.jdbc.SQLServerDataSource ds=

new

com.microsoft.sqlserver.jdbc.SQLServerDataSource();

ds.setServerName(

"MIROSŁAW-PC\\SQL"

);

ds.setDatabaseName(

"Northwind"

)

//ds.setIntegratedSecurity(true);

ds.setPassword(

"abc"

); ds.setUser(

"abc"

);

Connection con = ds.getConnection();

Statement stm =con.createStatement();

stm.execute(

"select count(*) from [Order Details]"

);

stm.getResultSet().next();

System.

out

.println(stm.getResultSet().getInt(1));

con.close();

}

catch

(Exception e){}

Połączenie, wykonanie prostego zapytania, rozłączyć

background image

83

com.microsoft.sqlserver.jdbc.SQLServerDataSource ds=

new

com.microsoft.sqlserver.jdbc.SQLServerDataSource();

ds.setServerName(

"127.0.0.1"

);

ds.setDatabaseName(

"CJDate"

);

ds.setUser(

"abc"

);ds.setPassword(

"abc"

);

java.sql.Statement stmt=ds.getConnection().createStatement();

stmt.execute(

"select * from SPJ"

);

while

(stmt.getResultSet().next())

{

for

(

int

i=1;i<=stmt.getResultSet().getMetaData().getColumnCount();i++)

{ System.

out

.print(stmt.getResultSet().getString(i));

System.

out

.print(

'\t'

);

}

System.

out

.println();

}

Połączenie, wypisanie zbioru wynikowego, prawie ManagementStudio

background image

84

Zadania
1) Posłużyć się integrated security. Wymagana dodatkowa

konfiguracja

2) Uruchomić przykłady conntectDS i connectURL
3) Nawiązać połączenie korzystając z connectURL i

integrated security

4) Uruchomić przykłady z wykładu w Eclipse


Wyszukiwarka

Podobne podstrony:
bazy danych druga id 81754 Nieznany (2)
Bazy danych kolo 2 1 id 81756 Nieznany
bazy danych kol 2 id 81577 Nieznany (2)
bazy danych wyk2 id 81712 Nieznany (2)
bazy danych wyklad1 id 81713 Nieznany (2)
Bazy Danych bd4 id 633777 Nieznany (2)
Bazy danych 07 id 81462 Nieznany (2)
bazy danych wyk id 81390 Nieznany (2)
bazy danych sql id 81694 Nieznany
BAZY danych wyk id 81710 Nieznany (2)
Bazy Danych kolokwium1 id 81578 Nieznany (2)
bazy danych wyklady id 81711 Nieznany (2)
Bazy danych egzamin(1) id 81477 Nieznany
Bazy Danych bd5 id 633778 Nieznany (2)
bazy danych druga id 81754 Nieznany (2)
Bazy danych kolo 2 1 id 81756 Nieznany
bazy danych kol 2 id 81577 Nieznany (2)
IELTS Secrets id 209543 Nieznany

więcej podobnych podstron