SQL 1

Werbung
3 SQL
InformationssystemefürIngenieure
Herbstsemester 2016
“SQL is intergalactic data speak.”
-- Michael Stonebraker
“If we adopt Oracle [for our SQL tutorial],
we don’t have to [ … ] pretend that SQL is a standard.”
-- Philip Greenspun
“SQL ≠ The Relational Model.”
-- Christopher Date
“In theory, there is no difference between practice and theory.
But in practice, there is.”
-- Jan L.A. van de Snepscheut
R.Marti
ZieldesKapitels
• Kenntnisder"Datensprache"SQLzurDefinition,ManipulationundAbfragevon
Datenbanken,die(mehrodermindergetreu)aufdemRelationenmodellbasieren.
• InsbesonderesolltenSieinderLagesein
–
nicht-trivialeAnfragenübermehrere(vorgegebene)Tabellen(≈Relationen)zuformulieren
–
(einfache)ManipulationenvonDatenin(vorgegebenen)Tabellendurchzuführen,d.h.neueDatenzu
Tabellenhinzufügen,sowiebestehendeDateninTabellenverändernoderlöschen
–
Eine(vorgegebene)DefinitionvonTabellenzuverstehen,inklusivederWirkungsweisederwichtigsten
Integritätsbedingungen(notnull,primarykeyundforeignkey)
GrundfürdieVermittlungdiesesStoffs
• SQLwirdseitüber25JahreninderPraxiseingesetztundistweitverbreitet–
auchheutenoch,trotzbekannterLimitationendesRelationenmodells
• DerEinflussvonSQListauchinSprachenfür"modernere"Datenbanksystemezuspüren,
z.B.inOQL(fürobjektierteDatenbanken),inXQuery(fürXMLDaten),sowieinHiveQL(für
verteilte"BigData"File-SystemewieHadoopHDFS)
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
2
GeschichtevonSQL (StructuredQueryLanguage)
1974
IBM Research:SEQUEL-XRM(StructuredEnglish-likeQueryLanguage)
1976
IBM Research:SEQUEL-2inSystemR
1980
RSI(RelationalSoftwareInc.,heute:Oracle):Oracle V2alserstes
kommerziellesSQL-Produkt,basierendaufIBMResearchPublikationen
1981
1983
IBM:SQL/DS
IBM:DB2 fürMVSBetriebssystem(1983)
1986
ANSI/ISO:SQL-86(späterSQL-89)Standard,ca.150Seiten
1992
ANSI/ISO:SQL-92(SQL2)Standard,ca.600Seiten
allg.Konsistenzbedingungen(nievollrealisiert!),CLI(Call LevelInterface)
1999
ANSI/ISO:SQL:1999(SQL3)Standard,ca.3000Seiten
verschiedeneLevels,insbesondererelevant:CoreSQL:1999
Objekt-orientierteErweiterungen,RekursiveAnfragen,ErweiterungenfDatenanalyse(OLAP)
...andthe storycontinues:SQL:2003,SQL:2006,SQL:2008,SQL:2011,...
see alsohttp://en.wikipedia.org/wiki/SQL
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
3
GeschichtevonSQL:DonChamberlin
Geschichte/3
• DonChamberlinholdsaPh.D.fromStanfordUniversity.
I
Don Chamberlin holds a Ph.D. from
• HeworkedatAlmadenResearchCenterdoingresearch
Stanford University.
ondatabaselanguagesandsystems.
I He worked at Almaden Research Center
doing research on database languages and
systems.
• HewasamemberoftheSystemRresearchteam
I He was a member of the System R research
team that developed much of today’s
thatdevelopedmuchoftoday’srelationaldatabase
technology.
•
relational database technology
I
He designed the original SQL database language.
I
In 2005 Don Chamberlin received an honory doctoral degree from
the University of Zürich for his work on SQL.
HedesignedtheoriginalSQLdatabaselanguage.
http://www.almaden.ibm.com/cs/people/chamberlin/
• In2005,DonChamberlinreceivedanhonorydoctoraldegreefromtheUniversity
ofZurichforhisworkonSQL.
InfO12, SQL
4/63
M. Böhlen, ifi@uzh
• seealsohttp://www.almaden.ibm.com/cs/people/chamberlin/
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
4
SQLTerminologie(imVergleichzumRelationenmodell)
• SQL basiertzwaraufdenKonzeptendesRelationenmodells,verwendetaberin
vielenBereicheneineeigene(oft"vereinfachte")Terminologie,insbesondere
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
5
UnterschiedezwischenSQLunddemRelationenmodell
SQL weichtteilweisevonKonzeptendesRelationenmodellsab.
• EineRelation(inderMathematikwieimDatenbank-Bereich)isteineMenge(set),d.h.,
DuplikatevonTupelnsindverboten.
EineSQLTabelleisteineMulti-Menge(multiset,auchbag),
d.h.,DuplikatevonZeilensindgrundsätzlicherlaubt.
Grund:DasEntdeckenvonDuplikatenist(fürgrosseTabellen)"teuer".
• In SQL istdieReihenfolgederAttribute(columns)einerTabellefix – gemässDefinitionin
derjeweiligenCREATE TABLE Anweisung.
• IneinerSQLSELECT AnweisungkanneinAttribut(column)mitgleichemNamenmehrfach
auftreten– esseidenn,dieSELECT AnweisungistTeileinerView-Definition.Solche
AttributemüssenmitdemNamenderjeweiligenTabellequalifiziert werden,z.B.
R.A stehtfürAttributA inTabelleR,S.A fürAttributA inTabelleS.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
6
PlayersimSQLDBMSMarkt
• "Elephants"(inalphabetischerReihenfolge)
– IBMmitDB210.5(forLinux/Unix/Windows)/DB211forz/OS
– MicrosoftmitSQLServer2014/SQLServer2016
– OraclemitOracle12c
• "NichePlayers",z.B
– Teradata
– SAPHana
– Sybase
• PublicDomain,z.B.
– MySQL5.7
– PostgreSQL9.6
– MonetDB
• DieSQLVersionendieserProdukte
– habeneinengemeinsamenKern(≈CoreSQL:1999≈SQL1989)
– kommerzielleProduktehabenmeisteigeneErweiterungen,umsichzupositionieren
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
7
SQLÜberblick
• DataDefinitionLanguage(DDL)
– DefinitionvonTabellen,Sichten:CREATE TABLE,CREATE VIEW,ALTER TABLE
– DefinitionvonIntegritätsbedingungen:CREATE ASSERTION
• DataManipulationLanguage(DML)
– Datenbank-Anfragen:SELECT
– Datenbank-Änderungen:INSERT,UPDATE,DELETE
• DataControlLanguage(DCL)
– z.B.Autorisierung:GRANT,REVOKE
• SchnittstellenzuProgrammiersprachen
– viaPrecompiler:EmbeddedSQL,DynamicSQL,SQLJ
– viaprozeduraleSchnittstelle:CLI(z.B.ODBCfürC),JDBCfürJava
• ProzeduraleElemente:SQL/PSM(bzw.PL/SQLinOracle,…)
– z.B.CREATE PROCEDURE
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
8
DefinitionvonTabellen(üblicheForm):Bsp.mitSchlüsselkandidaten
CREATE TABLE Products (
PrdNo
INTEGER
NOT NULL,
PrdDescr
VARCHAR(30) NOT NULL,
Weight
FLOAT
NOT NULL CHECK (Weight > 0.0),
...
►
CONSTRAINT PK_Products PRIMARY KEY (PrdNo),
CONSTRAINT AK_Products UNIQUE (PrdDescr)
);
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
9
Beispiel:Lieferdatenbank
Products
PRIMARY KEY (PrdNo)
beimEinfügen(INSERT)einesTupels
in Products wirdüberprüft,ob PrdNo
eindeutigbleibt
PrdNo PrdDescr
901 'Mouse*Logitech'
902 'Hard*Drive*LaCie'
903 'Speaker*Bose'
Weight Price Warehouse Stock
20
20.00 'Zürich'
1500 450.00 'Bern'
700 600.00 'Luzern'
10000
400
100
ebensobeimÄndern (UPDATE)
einerPrdNo
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
10
DefinitionvonTabellen(üblicheForm):Bsp.mitFremdschlüssel
CREATE TABLE Products (
PrdNo
INTEGER
NOT NULL,
PrdDescr
VARCHAR(30) NOT NULL,
Weight
FLOAT
NOT NULL CHECK (Weight > 0.0),
...
üblicheReihenfolgebeiTabellendefinition:
CONSTRAINT PK_Products PRIMARY KEY (PrdNo),
- Columns
CONSTRAINT AK_Products UNIQUE (PrdDescr)
(=Attribute)
);
- PrimaryKey
(=Primärschlüssel)
CREATE TABLE Orders (
- UniqueConstraints
OrdNo
INTEGER
NOT NULL,
(=übrigeSchlüsselkandidaten)
PrdNo
INTEGER
NOT NULL,
- ForeignKeys
CusNo
INTEGER
NOT NULL,
(=Fremdschlüssel,sofernvorhanden)
...
Status
VARCHAR(10) NOT NULL DEFAULT '1 ordered',
OrderDate DATETIME
NOT NULL,
ShipDate
DATETIME
NOT NULL,
CONSTRAINT PK_Orders PRIMARY KEY (OrdNo),
CONSTRAINT AK_Orders UNIQUE (OrderDate, PrdNo, CusNo),
CONSTRAINT FK_OrderedProducts
►
FOREIGN KEY (PrdNo) REFERENCES Products(PrdNo),
CONSTRAINT FK_OrderingCustomers
FOREIGN KEY (CusNo) REFERENCES Customers(CusNo)
);
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
11
Beispiel:Lieferdatenbank
Products
PRIMARY KEY (PrdNo)
PrdNo PrdDescr
Weight Price Warehouse Stock
901 'Mouse*Logitech'
902 'Hard*Drive*LaCie'
20
20.00 'Zürich'
1500 450.00 'Bern'
903 'Speaker*Bose'
700 600.00 'Luzern'
10000
400
100
beimLöschen(DELETE)einesTupelsinProducts wirdüberprüft,
obkeinTupelinOrders diesenWertreferenziert
FOREIGN KEY PrdNo REFERENCES Products(PrdNo)
Orders
OrdNo CusNo PrdNo Qty Amount
67890
101
901 100
1800.00
67891
101
901 100
1800.00
67892
101
902
8
3240.00
67893
102
903
1
R.Marti
beimEinfügen(INSERT)einesTupelsinOrders wirdüberprüft,
obinProducts einTupelmitdemWertvonPrdNo als
Primärschlüsselexistiert
Status
OrderDate ShipDate
ebensobeimÄndern
'3*paid'
2013007016 2013007020
(UPDATE)einerPrdNo
'3*paid'
2013007021 2013007028
in Orders
'1*ordered' 2013009020 9999012031
oderinProducts
480.00 '2*shipped' 2013009020
2013009021
InformationssystemefürIngenieure2016 – 3SQL
12
EBNFNotationzurBeschreibungderSyntax
SyntaxElement
Syntaxelement,für daseine Definitionanzugeben ist
(sog.Nichtterminalsymbol)
RESERVED
reserviertes Wort,welches im Quelltext sovorkommt
(sog.Terminalsymbol)
"s"
Terminalsymbol s,welches im Quelltext sovorkommt
abg
Folge von(Nichtterminal- undTerminal-)Symbolen
a|b
entweder dasSymbola oder dasSymbolb (aber nicht beide)
[a]
dasSymbola ist optional
(0oder 1Vorkommen vona)
{a}
dasSymbola kann wiederholt werden
(0,1oder mehrere Vorkommen vona)
Klammern ()werden verwendet umGruppierungen zu kennzeichnen:
a |b g bedeutet
entweder a oder dieFolge b g
(a |b )g bedeutet
entweder dieFolge a g oder dieFolge
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
bg
13
EinigeBemerkungenzuSQLSyntax-Konventionen
ImdiesemTextwerdenfürreservierteWorteGrossbuchstabenverwendet
(z.B.TABLE).Diesistjedochnichtzwingend.
EinName(TableName,TableAlias,ColumnName,ColumnAlias)mussmiteinemBuchstaben
beginnen,gefolgtvonBuchstaben,ZiffernoderderUnterlänge(underscore)_.
EineKonstante(hierLiteral genannt)hatjenachDatentypfolgendeForm
- eineFolgevonZiffernmitoderohneVorzeichen,z.B.123 ,-45
- eineFix- oderGleitkommazahl,z.B.6.789 ,-1.23E4 ,+0.1
- einTextderForm'Dies ist ein Text' oder'John''s Home'
InSQLspieltGross-/KleinschreibungnurinnerhalbvonText-KonstanteneineRolle!
DiefolgendenSchreibweisenvonNamen werdendemzufolgealsidentisch angesehen:
FAMILYNAME,familyname,FamilyName undfamilyName.
Nichtidentischsindjedochz.B.dieText-Konstanten'SWISS','Swiss' und'swiss' .
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
14
DefinitionvonTabellen:SyntaxinEBNF
TableDef = CREATE TABLE TableName "(" TableElementDef { "," TableElementDef } ")" .
TableElementDef = ColumnDef | [ CONSTRAINT ConstraintName ] TableConstraintDef .
ColumnDef = ColumnName DataType [ DEFAULT Literal ] { ColumnConstraintDef } .
ColumnConstraintDef = NOT NULL | PRIMARY KEY | UNIQUE
| CHECK "(" SearchCondition ")" | REFERENCES TableName [ "(" ColumnName ")" ] .
TableConstraintDef = ( PRIMARY KEY | UNIQUE ) "(" ColumnList ")"
| CHECK "(" SearchCondition ")"
| FOREIGN KEY "(" ColumnNameList ")" REFERENCES Table [ "(" ColumnNameList ")" ] .
ColumnList = ColumnName { "," ColumnName } .
DataType = INTEGER | REAL | CHAR | VARCHAR "(" Length ")" | DATETIME | … .
•
TableName undColumnName sindNamen,Literal eineKonstante(Zahl,Text,Datum).
SearchCondition wirdspäterdefiniert.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
15
EinfacheAnfragen:Syntax(vereinfacht,unvollständig)
Query =
Subquery { ( UNION | INTERSECT | EXCEPT ) [ ALL ] Subquery }
[ ORDER BY OrderItem { "," OrderItem } ] .
Subquery =
SELECT [ DISTINCT ] ( ProjectionList | "*" )
FROM TableExpr { "," TableExpr }
[ WHERE SearchCondition ]
[ GROUP BY ColumnRef { "," ColumnRef }
[ HAVING SearchCondition ] ] .
ProjectionList = ScalarExpr [ [ AS ] ColumnAlias ] { "," ScalarExpr [ [ AS ] ColumnAlias ] } .
ScalarExpr = ColumnRef | Literal | … .
ColumnRef = [ TableName "." ] ColumnName .
TableExpr = ( TableName | Subquery ) [ [ AS ] TableAlias ] .
OrderItem = { ColumnRef | Integer } [ ASC | DESC ] .
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
16
SQLAnfragen undRelationenalgebra
SeiA einAttributeinerRelationR,
B einAttributeinerRelationS
undp eineFormel,dieAttributeausdenRelationenR undS referenziert.
EineQueryderForm
SELECT A, B
FROM
WHERE
R, S
p
entspricht– sofernkeineDuplikateeliminiertwerdenmüssen– dem
Relationenalgebra-Ausdruck
pA, B ( sp ( R ´ S ) )
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
17
Selektion:BeispielmiteinfachemSelektionsprädikat
FindealleZürcherKunden
s CusCity = 'Zürich' (Customers)
SELECT *
FROM
Customers
WHERE CusCity = 'Zürich'
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
18
Selektion:BeispielmitzusammengesetztemPrädikat
FindealleZürcherKunden,dieunsGeldschulden
s CusCity = 'Zürich' Ù BalanceDue > 0 (Customers)
SELECT *
FROM
Customers
WHERE CusCity = 'Zürich' AND BalanceDue > 0
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
19
Projektion:Beispiel
FindeBeschreibung,LagerortundLagerbestandfüralleProdukte
p PrdDescr, Warehouse, Stock (Products)
SELECT PrdDescr, Warehouse, Stock
FROM
Products
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
20
SelektionundProjektion(IntegrierteÜbung)
Beschreibung,LagerortundLagerbestand
fürProdukte,derenLagerbestand<300 ist
p PrdDescr, Warehouse, Stock (s Stock < 300 (Products))
?
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
21
Vereinigung:Beispiel
Nummer,Beschreibung,
GewichtundPreis,sowohl
fürbestehendewieauch
fürneueProdukte
∪
p PrdNo, PrdDescr, Weight, Price (Products) ∪ NewProducts
SELECT
FROM
UNION
SELECT
FROM
R.Marti
PrdNo, PrdDescr, Weight, Price
Products
PrdNo, PrdDescr, Weight, Price
NewProducts
InformationssystemefürIngenieure2016 – 3SQL
22
JoinmitKreuzproduktundSelektion:KonkretesBeispiel
×
p OrdNo, CusNo, PrdNo, Qty, ShipDate, CusName ( s CusNo1 = CusNo ( Orders × r CusNo1 ß CusNo (Customers) ) )
SELECT OrdNo, Orders.CusNo, Qty, ShipDate, CusName
FROM
Orders, Customers
WHERE Orders.CusNo = Customers.CusNo
Result_12
OrdNo CusNo PrdNo Qty ShipDate CusName
R.Marti
67890
101
901 100 2013)07)20 'Legrand'
67891
101
901 100 2013)07)28 'Legrand'
67892
101
902
8 9999)12)31 'Legrand'
67893
102
903
1 2013)09)21 'Studer'
InformationssystemefürIngenieure2016 – 3SQL
23
Modell für Auswertung einfacher SQLAnfragen
DieKorrespondenzeinereinfachen SQL-AnfragezurRelationenalgebra bildetdie
Basisfüreinkonzeptionelles ModellderAnfrageauswertung:
1. FormedasKreuzproduktderTabelleninderFROM-Klausel.
´
2. EliminiereZeilen,welchedieWHERE-Klausel nichterfüllen.
s
3. EvaluieredieAusdrückeinderSELECT-Klausel.
p
4. EliminiereDuplikatefallsDISTINCT spezifiziertwurde.
(*)
(*):inRelationenalgebra nichtnötig:JedesElementeinerMengekommtnureinmalvor
Datenbanksystemeverwenden meisteffizientereStrategien;
sowirdz.B.einKreuzproduktnicht vollständigberechnet("materialisiert")
wenndiesnichtnötigist.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
24
SQLAnfragen:Beispiele(1)
►
Selektion
Q1
Kunden,dieunsGeldschulden.
SELECT CusNo, CusName, CusCity, BalanceDue, Discount
FROM
WHERE
Customers
BalanceDue > 0
oder einfacher, abernurfür interaktive Anfragenempfohlen
SELECT *
FROM
WHERE
R.Marti
Customers
BalanceDue > 0
InformationssystemefürIngenieure2016 – 3SQL
25
SQLAnfragen:Beispiele(2)
Kreuzprodukt
►
+Selektion
+Projektion
Q2
NamenderKunden,dieeinegelieferte(nochunbezahlte)Bestellung
erhaltenhaben,dievorAnfangSeptember2013 erfolgte.
pCusName (sCusNo = D Ù Status = '2 shipped' Ù ShipDate < 2013-09-01 (rD ß CusNo (Orders) × Customers))
SELECT CusName
FROM
Customers, Orders
WHERE
Orders.CusNo = Customers.CusNo
AND Status = '2 shipped'
AND ShipDate < DATE '2013-09-01'
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
26
SQLAnfragen:Beispiele(3)
►
Mengendifferenz
+Projektion
Q3
KundennummernderKunden,vondenenkeineBestellung registriertist.
pCusNo (Customers) – pCusNo (Orders)
SELECT CusNo
FROM
Customers
EXCEPT
SELECT CusNo
FROM
Orders
inOracleMINUS stattEXCEPT
inMySQLnichtunterstützt
aberaufandereArtlösbar(➛ siehespäter)
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
27
SQLAnfragen:Beispiele(4)
Q4
NamenderKunden,vondenenmindestenseineBestellung registriertist.
pCusName ( sCusNo = D ( Customers × rD ß CusNo (Orders) ) )
SELECT Customers.CusName
FROM
Customers, Orders
WHERE
Orders.CusNo = Customers.CusNo
auchaufandereArtlösbar(➛ siehespäter)
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
28
SQLAnfragen:Beispiele(5)
►
Kreuzproduktvon3Tabellen
Q6
NamenderZürcherKunden,dieeinProdukt ausZürichbestellt haben.
SELECT Customers.CusName
FROM
WHERE
Customers, Orders, Products
Orders.CusNo = Customers.CusNo
AND Products.PrdNo = Orders.PrdNo
AND Customers.CusCity = 'Zurich'
AND Products.Warehouse = 'Zurich'
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
29
SQLAnfragen:Beispiele(6)
VerwendungderJoin-Syntax
►
(entsprichtTheta- bzw.Equi-Join)
Q6
NamenderZürcherKunden,die
einProdukt ausZürichbestellt haben.
SELECT Customers.CusName
FROM
Customers
JOIN Orders ON Orders.CusNo = Customers.CusNo
JOIN Products ON Products.PrdNo = Orders.PrdNo
WHERE
AND Customers.CusCity = 'Zurich'
AND Products.Warehouse = 'Zurich'
Bem.: Esgibtaucheinen NATURAL JOIN Operator,
dessenVerwendungaberhöchstensfürinteraktiveAnfragenempfohlenwird.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
30
SQLAnfragen:Beispiele(7)
Verwendungvon
Tabellen-Alias
►
(auchKorrelationsvariablegenannt)
Q8
NamenvonPaarenvonKunden,dieinderselbenStadtwohnen,mitStadt.
pCusName, OtherName, CusCity (
Customers ⋈ OtherCity = CusCity Ù OtherNo > CusNo
rOtherNo ß CusNo, OtherName ß CusName, OtherCity ß CusCity ( Customers )
)
SELECT c1.CusName, c2.CusName AS OtherName, c1.CusCity
FROM
WHERE
R.Marti
Customers c1, Customers c2
c2.CusCity = c1.CusCity AND c2.CusNo > c1.CusNo
InformationssystemefürIngenieure2016 – 3SQL
31
SQLAnfragen:Beispiele(8)
►
Join-Syntax+Tabellen-Alias
Q6
NamenderZürcherKunden,die
einProdukt ausZürichbestellt haben.
SELECT c.CusName
FROM
Customers c
JOIN Orders o ON o.CusNo = c.CusNo
JOIN Products p ON p.PrdNo = o.PrdNo
WHERE
AND c.CusCity = 'Zurich'
AND p.Warehouse = 'Zurich'
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
32
EinigeDetailszurSELECTKlausel
• DasSymbol* stehtfüralleKolonnenallerTabellenderzugehörigenFROM Klausel.
• EskönnenstattKolonnennamenoderKonstantenAusdrückeverwendetwerden,z.B.
Qty*Amount*(1–Discount),ABS(-1),CHAR_LENGTH('Chamberlin')
FamName || ', ' || FirstName,TRIM(UPPER('Codd
'))
• Kolonnenkönnenumbenanntbzw.neubenanntwerden,z.B.
Qty*Amount*(1–Discount) AS TotalAmount
FamName || ', ' || FirstName AS FullName
• WennineinemAusdruck(ScalarExpr)derWerteinerKolonneA einesTupelsNULL
("unbekannt")ist,dannistderWertdesganzenAusdrucksNULL,z.B.wennDiscount
denWertNULL hat,dannhatauchQty*Amount*(1–Discount) denWertNULL.
• KolonnenkönnendurcheineSubquery,d.h.( SELECT ScalarExpr FROM ... ) berechnet
werden,soferndieseSubqueryhöchstens einTupelzurückliefert.
FallsdieSubquerykeinTupelliefert,soistderWertNULL (vglspätere Folie).
• DasreservierteWortDISTINCT eliminiertDuplikate(vglfolgendeFolie).
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
33
EliminiationvonDuplikatenmitDISTINCT:Beispiel
InwelchenStädten wohnenunsereKunden?
p CusCity (Customers)
SELECT DISTINCT CusCity
FROM
Customers
SELECT CusCity
FROM
Customers
Result_14
Result_13
CusCity
CusCity
'Genève'
'Genève'
'Zürich'
R.Marti
Relationenmodell(Theorie)
EineRelation isteineMenge.
SQL(Praxis) 'Zürich'
EinTable isteineMulti-Menge. 'Zürich'
InformationssystemefürIngenieure2016 – 3SQL
34
WiekönnenDuplikateentstehen?
DasResultat einer Anfrage enthält infolgenden Fällen Duplikate:
•
BeieinerAnfragederFormSELECT * FROM T (mitoderohneWHERE-Klausel)aufeinerTabelle
T, fürdiewedereinPRIMARY KEY nocheineUNIQUE Bedingung spezifiziert wurde, undindie
mehrereidentischeTupel eingefügtwurden.
⇒ FürjedeTabellesollteeinPRIMARY KEY spezifiziertwerden.
•
WennnacheinerProjektiondieverbleibendenKolonnenkeinenSchlüsselkandidaten mehr
enthalten
(vgl.BeispielaufdervorherigenFolie).
•
BeieinerVereinigungvonzweiTabellenmitUNION ALL.
ZurEliminationvonDuplikatenmussSELECT DISTINCT spezifiziertwerden– idealerweise
jedochnurdann,wenndiesauchwirklichnötigist.
IndenmeistenSystemenwirdbeiSELECT DISTINCT dasResultatnachpotentiellenDuplikaten
abgesucht,selbstwenneineAnfragenieDuplikateproduzierenkann!
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
35
SkalarfunktionenundOperatoren– einunvollständiger Überblick
•
numerischeOperatoren:
NumExpr+NumExpr, NumExpr-NumExpr, NumExpr*NumExpr, NumExpr/NumExpr, ABS(NumExpr), …
•
Funktionen,dienumerischeWerteliefern:
CHAR_LENGTH(StringExpr), POSITION(StringExpr IN StringExpr), …
•
Funktionen,dieZeichenkettenliefern:
•
StringExpr || StringExpr
SUBSTRING(StringExpr START Pos FOR Len)
UPPER(StringExpr)
Konkatenation vonZeichenketten
TeileinerZeichenkette
KonversionzuGrossbuchstaben
LOWER(StringExpr)
TRIM(StringExpr)
CURRENT_USER
KonversionzuKleinbuchstaben
EliminationvonLeerzeichenvornundhinten
Benutzername
Funktionen,dieDatumswerteliefern:
CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
36
SubqueriesalsSkalarfunktioninderSELECT-Klausel
•
EineSELECT-Anweisung kannalsSkalarfunktion betrachtetwerden,fallssieeineTabellebestehendaus
höchstenseinerZeilemiteinerSpalteliefert.FallsdasResultateineZeileumfasst,dannistderSkalarder
WertderSpalte,sonstistderSkalarderWertNULL.)
SomitkanneinesolcheSubqueryauchineinerSELECT-Klausel stehen:
SELECT ( SELECT COUNT(*) + 1
FROM
Products otherProduct
WHERE otherProduct.Price > givenProduct.Price ) AS WhatAmI,
givenProduct.Price, givenProduct.PrdDescr
FROM
Products givenProduct
ORDER BY 1
•
COUNT(*) isteineAggregatfunktion,welchedieAnzahlTupel ineinerTabellezählt
(vgl.spätereFolieüberAggregatfunktionenundderenSyntax,mitBeispielen)
•
Frage:WasproduziertdieobigeAnfrage?WofürstehtdieKolonneWhatAmI?
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
37
EinigeDetailszurWHEREKlausel
• DieWHERE KlauselgibtdiejenigenTupelzurück,fürwelchedieEvaluationderganzen
SearchCondition denWahrheitswertT (fürtrue bzw.wahr)ergibt.
Bem.:T sowieF (fürfalse bzw.falsch)sindkeine KonstanteninSQL.
• DieSearchCondition beinhaltetals"atomare"BedingungendieüblichenVergleichsoperationen(=,<,<=,>=,<>)sowieVerknüpfungensolcherBedingungenmitAND,OR und
NOT:
• AusserdemgibtesunteranderemeinigeweitereeinfacheBedingungenwie
BETWEEN ScalarExpr AND ScalarExpr sowieScalarExpr LIKE Pattern.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
38
VergleichemitNullwerten
NULL stehtfür"Wertunbekannt"(allenfallsfür"Wertnichtanwendbar")
•
DasResultateinesVergleichsinderWHERE KlauselzwischenNULL und
–
einem"regulären"(nicht-NULL)Wertergibtunbekannt(unknown)
–
demWertNULL selbstergibtebenfallsunbekannt(unknown)
daeinunbekannterWertgleich(bzw.kleiner,grösseroderungleich)wieeinanderer
(bekannteroderunbekannter)Wertseinkann!
• Dazuwirdeine3-wertigeLogikverwendet,wobei? fürdenlogischenWert"unbekannt"
steht.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
39
Bereichsprädikate:SyntaxundBeispiel
BetweenPredicate = ScalarExpr [ NOT ] BETWEEN ScalarExpr AND ScalarExpr .
• Kunden,derenRabattzwischen10und20Prozentliegt .
SELECT *
FROM
Customers
WHERE Discount BETWEEN 0.10 AND 0.20
• ObigeFormulierungentsprichtderfolgendenFormulierung:
SELECT *
FROM
Customers
WHERE Discount >= 0.10 AND Discount <= 0.20
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
40
Mustervergleiche:SyntaxundBeispiele
LikePredicate = ColumnRef [ NOT ] LIKE Literal [ ESCAPE Literal ] .
wobeiimZeichenketten-LiteralnachLIKE
_ füreinbeliebigesZeichensteht
% füreinebeliebigeFolgevonZeichen(auchdieleereFolge)steht
alleanderenZeichenfürsichselbststehen
DasLiteralnachESCAPE definiertein„Escape“-Zeichen,z.B.'\'.
•
Kunden,derenNamemit‘A‘ beginnt .
SELECT * FROM Customers
WHERE CusName LIKE 'A%'
•
Produkte,inderen Beschreibung‘DVD’vorkommt.
SELECT * FROM Products
WHERE PrdDescr LIKE '%DVD%'
•
Produkte,deren Beschreibungmit‘P_A’undeinembeliebigenZeichenendet.
SELECT * FROM Products
WHERE PrdDescr LIKE '%P\_A_' ESCAPE '\'
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
41
VergleichemitNullwerten:SyntaxundBeispiele
NullTest = ColumnRef IS [ NOT ] NULL .
• Produkte,derenLagerortunbekanntist .
SELECT *
FROM
Products
WHERE Warehouse IS NULL
Achtung:
ColumnRef = NULL
istlegal,ergibtaber
unknown,egalwas
ColumnRef enthält!
• Produkte,derenMengeanLagerbekannt(nichtNULL)ist .
SELECT *
FROM
Products
WHERE Stock IS NOT NULL
bzw.
SELECT *
FROM
Products
WHERE NOT (Stock IS NULL)
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
42
Subqueries– QuantifizierteVergleiche:Syntax
QuantifiedPredicate = ScalarExpr ( "=" | "<>" | "<" | "<=" | ">=" | ">" )
[ ALL | ANY | SOME ] "(" Subquery ")" .
Seien
x einSkalar,
S dasResultateinerSubqueryderForm SELECT y FROM R und
q einerderobigenVergleichsoperatoren.
Danngilt:
x q ANY ( SELECT y FROM R )
x q SOME ( SELECT y FROM R )
sinderfüllt,fallsgilt: $y Î S: x q y
x q ALL ( SELECT y FROM R )
isterfüllt,fallsgilt:
"y Î S: x q y
(esexistierteiny inS sodassx q y )
(füralley inS giltx q y )
Auswertung:
ZuerstwirddieSubquery,dieS berechnet,ausgeführt,danachdieäussereQuery,
inderenWHERE-KlauselderquantifizierteVergleichauftriff.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
Empfehlung:
QuantifizierteVergleiche
vermeiden…
43
Subqueries– QuantifizierteVergleiche:Beipiele
QuantifiedPredicate = ScalarExpr ( "=" | "<>" | "<" | "<=" | ">=" | ">" )
[ ALL | ANY | SOME ] "(" Subquery ")" .
•
KundenmitdemgeringstenRabatt.
SELECT * FROM Customers
WHERE Discount <= ALL ( SELECT Discount FROM Customers )
•
Kunden,dienichtdengeringstenRabatthaben.
SELECT * FROM Customers
WHERE Discount > SOME ( SELECT Discount FROM Customers )
•
NamenallerKundendieeineunbezahlteLieferungerhielten,dievor2014erfolgte:
SELECT CusName FROM Customers
WHERE CusNo = ANY ( SELECT CusNo FROM Orders
WHERE Status = '2 shipped'
AND ShipDate < DATE '2014-01-01' )
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
44
Subqueries– Mengenzugehörigkeit:Syntax+Beispiele
InPredicate = ScalarExpr [ NOT ] IN "(" ( Literal { "," Literal } | Subquery ) ")" .
•
Kunden,dieinZürich,GenfoderBasel wohnen.
eineexpliziteListevonWerten
SELECT *
FROM
Customers
WHERE CusCity IN ( 'Zürich', 'Genf', 'Basel' )
•
NamenallerKunden,dieeineunbezahlteLieferungerhielten,dievorAnfangSeptember2013
erfolgte.
eineSubquery
SELECT CusName
Resultat:eineRelation
FROM
Customers
WHERE CusNo IN ( SELECT CusNo
FROM
Orders
WHERE Status = '2 shipped'
AND ShipDate < DATE '2013-09-01' )
Konzeptionelles Auswertungsmodell:
Zuerst wird dieSubquery einmal ausgewertet,danach dieäussere Query.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
45
Subqueries– Mengenzugehörigkeit:Semantik
InPredicate = ScalarExpr [ NOT ] IN "(" ( Literal { "," Literal } | Subquery ) ")" .
•
x IN ( c1, c2, … , cn )
istäquivalentzu
x = c1 OR x = c2 OR … OR x = cn
•
x IN ( SELECT y FROM R )
istäquivalentzu
x = ANY ( SELECT y FROM R )
•
x NOT IN ( SELECT y FROM R )
istäquivalentzu
x <> ALL ( SELECT y FROM R )
.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
46
Subqueries– Existenz
ExistenceTest = [ NOT ] EXISTS "(" Subquery ")" .
•
NamenallerKunden,dieeineunbezahlteLieferungerhielten,dievorAnfangSeptember2013
erfolgte.
einekorrelierte Subquery
SELECT c.CusName FROM Customers c
WHERE EXISTS ( SELECT * FROM Orders o
WHERE o.CusNo = c.CusNo
AND o.Status = '2 shipped'
AND o.ShipDate < DATE '2013-09-01' )
•
NamenallerKunden,fürdiekeineBestellungregistriertist
SELECT c.CusName FROM Customers c
WHERE NOT EXISTS ( SELECT * FROM Orders o
WHERE o.CusNo = c.CusNo )
Konzeptionelles Auswertungsmodell:
Diekorrelierte Subquery wird für jeden Wertvonc.CusNo der äusseren Queryeinmal
ausgewertet.
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
47
SQLAnfragen:Beispiele(9)
Mengendifferenz:
kannstattmitEXCEPT
►
durchNOT EXISTS
ausgedrücktwerden
Q3
KundennummernderKunden,vondenenkeineBestellung registriertist.
pCusNo (Customers) – pCusNo (Orders)
SELECT CusNo
FROM
Customers
WHERE NOT EXISTS
SELECT
FROM
WHERE
(
*
Orders
Orders.CusNo = Customers.CusNo
)
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
48
Subqueries,derenResultateinSkalarwertist
DasResultat einer Subquery ist normalerweise eine Tabelle,d.h.ein BagvonZeilen
mit mehreren Spalten.
Ingewissen Fällen wissen wir,dass dasResultat ein Bagbestehend aus höchstens einer Zeile
mit einer Spalte sein sollte.
Dann darf dasResultat der Subquery als Skalarwert betrachtet werden.
(FallsdasResultat der Subquery leerist,wird der Skalarwert NULL zurückgegeben.)
•
Beispiel(skalare SubqueryinWHERE-Klausel):
Bestellnummer,LieferdatumundMengeausgelieferterBestellungendesProdukts‘DiskDrive‘.
(Annahme:KolonnePrdDescr istSchlüsselkandidatundalsUNIQUE deklariert.)
SELECT
FROM
WHERE
AND
R.Marti
OrdNo, ShipDate, Qty
Orders
Status = '2 shipped'
PrdNo = ( SELECT PrdNo
FROM
Products
WHERE PrdDescr = 'Disk Drive' )
InformationssystemefürIngenieure2016 – 3SQL
49
Scoping-RegelnfürNamenvonKolonnen
1. EinunqualifizierterNameeinerKolonneC ineinerSubqueryQ (bzw.ineinergeschachtelten
QueryQ) gehörtzueinerTabelleT inderFROM-KlauseldergleichenSubqueryQ,soferninQ
genaueineTabelleT miteineKolonnenamensC existiert.
2. WennesinQ mehrereTabellenmiteinerKolonnenamensC gibt,dannistdieSELECTAnweisungungültig.
3. WennesinQ keineTabellemiteinerKolonnenamensC gibt,dannwirddieSuchenachderzu
C gehörigenTabelleinderdieSubqueryQ umfassenden(Sub-)Queryrekursivfortgesetzt
(soferneinesolcheexistiert).
4. WennkeineumfassendeQueryexistiert,dannistdieSELECT-Anweisungungültig.
•
Beispiel:NamenallerKunden,fürdiekeineBestellungregistriertist
SELECT CusName
FROM
Customers
WHERE NOT EXISTS ( SELECT *
FROM
Orders
WHERE CusNo = Customers.CusNo )
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
50
ZusätzlicheJoin-SyntaxinSQL:1999
NamenallerKunden,dieeinedieeineunbezahlteLieferungerhielten,dievorAnfangSeptember2013
erfolgte
SELECT CusName
FROM
Customers c,
( SELECT CusNo FROM Orders
WHERE Status = '2 shipped'
o.ShipDate < DATE '2013-09-01') o
WHERE o.CusNo = c.CusNo
SELECT CusName
FROM
Customers c
JOIN Orders o ON o.CusNo = c.CusNo
WHERE Status = '2 shipped' AND ShipDate < DATE '2013-09-01'
wirdvonden
meistenDBMS’s
unterstützt
SELECT CusName
FROM
Customers
JOIN Orders USING(CusNo)
WHERE Status = '2 shipped' AND ShipDate < DATE '2013-09-01'
SELECT CusName
FROM
Customers NATURAL JOIN Orders
WHERE Status = '2 shipped'
AND ShipDate < DATE '2013-09-01'
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
Verwendungvon
NATURAL JOIN
wirdnichtempfohlen!
51
LeftOuterJoininSQL:1999
AlleInformationenüberalleStudenten(inkl.Programmierkenntnisse):
SELECT s.EnrolNo, s.Name, s.FCode, i.IT_Skill
FROM
Students s
LEFT OUTER JOIN IT_Skills i ON i.EnrolNo = s.EnrolNo
DieserlinkeäussereVerbund(leftouterjoin)istäquivalentzurfolgendenAnfrage:
SELECT s.EnrolNo, s.Name, s.FCode, i.IT_Skill
FROM
Students s, IT_Skills i
WHERE i.EnrolNo = s.EnrolNo
UNION ALL
-- no duplicate elimination needed => use ALL
SELECT s.EnrolNo, s.Name, s.FCode, NULL AS IT_Skill
FROM
Students s
WHERE NOT EXISTS (
SELECT *
FROM
IT_Skills i
WHERE i.EnrolNo = s.EnrolNo
)
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
52
Aggregatfunktionen:SyntaxundBeispiele
InderListederKolonnen(ScalarExpr)ineinerSELECT-Anweisung könnenauchAggregat-funktionen
erscheinen,dieausallenWerteneinerTabelle(bzw.allenWerteneinerGruppe,
siehespäter) einenAggregatwertberechnet.
AggregateFunction = "COUNT(*)"
| ( COUNT | SUM | AVG | MIN | MAX ) "(" [ DISTINCT ] ScalarExpr ")" .
DasZeichen* inCOUNT(*) bezeichneteinganzesTupel.
•
AnzahlProdukte,dieangebotenwerden
SELECT COUNT(*) FROM Products
oder:SELECT COUNT(PrdNo) FROM Products
-- PrdNo ist Primärschlüssel
oder:SELECT COUNT(Warehouse) FROM Products -- fallsWarehouse keine Nullwerte hat
-- COUNT(Column) ergibt dieAnzahl der Tupel,für dieColumn IS NOT NULL gilt
•
AnzahlOrte,andenenProduktegelagertwerden
SELECT COUNT(DISTINCT Warehouse) FROM Products
•
höchsterRabattallerKunden
SELECT MAX(Discount) FROM Customers
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
53
Aggregatfunktionen(2)
•
AnzahlKundenmiteinemRabatt,dergrösser als15%(0.15)ist
SELECT COUNT(*) FROM Customers WHERE Discount > 0.15
•
Kunden,diedenhöchstenRabattallerKunden erhalten
SELECT * FROM Customers
WHERE Discount = ( SELECT MAX(Discount) FROM Customers )
•
Kunden,dieeinenüberdurchschnittlichenRabatt erhalten
SELECT * FROM Customers
WHERE Discount > ( SELECT AVG(Discount) FROM Customers )
•
HöhedesGesamtumsatzes imJahr 2012
SELECT SUM(Qty*Price*(1.0-Discount)) AS YearlyRevenue
FROM
Orders o
JOIN Products p ON p.PrdNo = o.PrdNo
JOIN Customers c ON c.CusNo = p.CusNo
WHERE OrderDate BETWEEN DATE '2012-01-01' AND DATE '2012-12-31'
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
54
AggregationmitGruppenbildung:Beispiele
OftsollenAggregatwertenichtfüreineganzeTabelleberechnetwerden,sondernfürGruppenvonTupel,
dieingewissen(vorgegebenen)KolonnendengleichenWertbesitzen.
DieNamendieservorgegebenenKolonnenwerdeninderGROUP BY Klauselspezifiziert.
In denColumnSpecs derSELECT Klauseldürfendannnurfolgende Kolonnenstehen:
•
–
Kolonnen,dieinGROUP BY vorkommen(evt.alsArgumentevonOperatoren/Funktionen)
–
Kolonnen,diealsArgumentevonAggregatsfunktionenvorkommen
NummernderProdukteundderenGesamtverkaufszahlseit1.Januar 2013.
SELECT
FROM
WHERE
GROUP
•
PrdNo, SUM(Qty) AS TotalQty
Orders
OrderDate >= DATE '2013-01-01'
BY PrdNo
NummerundNamederStudentenmitderAnzahlderihnenbekanntenProgrammiersprachen.
SELECT s.EnrolNo, s.Name, COUNT(i.IT_Skill)
FROM
Students s
JOIN IT_Skills i ON i.EnrolNo = s.EnrolNo
GROUP BY s.EnrolNo, s.Name
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
55
AggregationmitGruppenbildung:Auswertung
IT_Skills
KonzeptionellesAuswertungsmodell(Beispiel):
EnrolNo
IT_Skill
NamederProgrammierspracheund
AnzahlderStudenten,diediese
Sprachekennen
‘87–604–I’
‘Java’
‘87–604–I’
‘C’
‘87–604–I’
‘SQL’
SELECT COUNT(EnrolNo) AS StudCount, IT_Skill
FROM
IT_Skills
GROUP BY IT_Skill
‘91–872–I’
‘Pascal’
‘91–872–I’
‘Java’
‘91–109–I’
‘Java’
1SortierenachGruppierungskolonne(n)
2BildeGruppen
3AggregiereinnerhalbderGruppen
StudCount
R.Marti
1
IT_Skill
3
EnrolNo
IT_Skill
‘87–604–I’
‘C’
‘87–604–I’
‘Java’
‘91–872–I’
‘Java’
1
‘C’
3
‘Java’
‘91–109–I’
‘Java’
1
‘Pascal’
‘91–872–I’
‘Pascal’
1
‘SQL’
‘87–604–I’
‘SQL’
InformationssystemefürIngenieure2016 – 3SQL
2
56
AggregationmitGruppenbildung:Beispiele
FürganzeGruppenkönnenmitHilfederHAVING Klausel zusätzlicheBedingungengestelltwerden.
•
NummernderProdukteundderenGesamtverkaufszahlab1.Januar 2013,
sofern diese Gesamtverkaufszahl grösser als 1000ist.
SELECT
FROM
WHERE
GROUP
HAVING
•
PrdNo, SUM(Qty) AS TotalQty
Orders
OrderDate >= DATE '2013-01-01'
BY PrdNo
SUM(Qty) > 1000
NamenderStädtemitdemdurchschnittlichenRabattderKundenderStadt,
soferndieAnzahldieserKundengrösser als10ist,
wobeidasResultatabsteigendgemäss durchschnittlichenRabattengeordnetseinsoll.
SELECT
FROM
GROUP
HAVING
ORDER
R.Marti
CusCity, AVG(Discount)
Customers
BY CusCity
COUNT(*) > 10
BY 2 DESC
-- Alternative: ORDER BY AVG(Discount) DESC
InformationssystemefürIngenieure2016 – 3SQL
57
KonzeptionellesModellfürdieAuswertungvonSQL
SELECT DISTINCT
ScalarExpressions,
AggregationFunctions
FROM
Tables
WHERE
FilterCondition
GROUP BY
Columns
HAVING
GroupFilterCondition
UNION ALL
OtherSubqueries
ORDER BY
1.
BerechnedasKreuzproduktderTabellen inder FROM-Klausel.
2.
Eliminiere Zeilen,welchedieFilterCondition derWHERE-Klauselnicht
erfüllen (inkl.ON BedingungenbeiVerwendungderJOIN Syntax).
3.
GruppieredieverbleibendenZeilengemässGROUP-BY-Klausel ...
4.
...undevaluiere AggregationFunctions umproGruppe1Tupelzu
produzieren.
5.
Eliminiere Zeilen,dieGruppenrepräsentieren, welchedie
GroupFilterCondition derHAVING-Klauselnichterfüllen.
6.
Evaluiere ScalarExpressions inderSELECT-Klausel.
7.
WendedieMengenoperatoren (UNION,INTERSECT,EXCEPT)aufdie
verbleibendenZeilensowieResultate derOtherSubqueries an.
8.
Sortiere dieTeilegemäss ORDER-BY-Klausel andeliminiere Duplikate
falls DISTINCT spezifiziertwurde
(oderdieMengenoperatorenohneALL spezifiziertwurden.)
Columns
R.Marti
InformationssystemefürIngenieure2016 – 3SQL
58
Herunterladen