88
Brandeis Consulting Die SELECT-Anweisung Jörg Brandeis

Die SELECT-Anweisung

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Brandeis Consulting

Die SELECT-AnweisungJörg Brandeis

Brandeis ConsultingDie SELECT-Anweisung…

▪ Ist die am häufigsten verwendete SQL-Anweisung überhaupt

▪ Ist nicht SQLScript-Spezifisch

▪ Wird von ABAP-Entwicklern in OpenSQL meistens nur in relativ einfacher Form

verwendet

▪ Ist extrem mächtig

▪ Kann sehr komplex werden

➔ Wir behandeln die SELECT-Anweisung, auch wenn Sie vielleicht schon bekannt

ist.

18.07.2018 SQLScript für BW-Berater 2

Brandeis ConsultingSELECT Anweisung vs. SELECT Abfrage

Eine SELECT-Anweisung beginnt mit dem Schlüsselwort SELECT und endet mit

einem Semikolon.

Eine SELECT-Abfrage ist ein Tabellenausdruck, der in anderen SQL-Anweisungen

verwendet wird. Z.B. als Unterabfrage.

18.07.2018 SQLScript für BW-Berater 3

Brandeis ConsultingDer Syntax der SELECT-Anweisung - Übersicht

SELECT <Feldliste>

FROM-Klausel

[WHERE <WHERE-Bedingung>]

[[GROUP BY <Gruppierung>

[HAVING <Having-Bedingung>]]

[ORDER BY <Sortierung>]

[LIMIT <Begrenzung>]

18.07.2018 SQLScript für BW-Berater 4

Brandeis Consulting

Feldliste

• Welche Felder/Spalten sind im Ergebnis der Ausgabe

WHERE Bedingung

• Welche Daten aus der Quelle sollen berücksichtigt werden

Aggregation

• Wie sollen die Daten zusammengefasst werden?

Wo sollen die Daten herkommen?

• FROM Klausen mit Tabellenausdrücken

SELECT

18.07.2018 SQLScript für BW-Berater 5

Brandeis ConsultingWas liefert eine SELECT-Abfrage zurück

Die Spalten einer SELECT-Abfrage werden durch die Feldliste festgelegt. In ABAP

steht hier häufig * für alle Spalten der Quelle.

Die Zeilen werden durch die Quellen in der FROM-Klausel und durch die WHERE-

Bedingung festgelegt. Gelegentlich auch durch GROUP BY und HAVING-Klausel

18.07.2018 SQLScript für BW-Berater 6

Brandeis ConsultingDie Feldliste

In der Feldliste können alle möglichen skalaren Ausdrücke stehen:

▪ Spaltennamen der Tabellen aus der FROM-Klausel

▪ Operatorausdrücke, z. B. für Berechnungen oder zum Verknüpfen von

Zeichenketten

▪ CASE-Ausdrücke für Fallunterscheidungen und Bedingungen

▪ Funktionsaufrufe

▪ Variablennamen

▪ Konstante Werte

▪ Unterabfragen mit SELECT

▪ Aggregatfunktionen

18.07.2018 SQLScript für BW-Berater 7

Brandeis ConsultingFeldnamen einer Abfrage

Jedes Feld in der Feldliste hat einen Namen. Dieser ist entweder

▪ mit AS explizit vergeben worden

▪ 1:1 aus dem Quellfeld übernommen, falls es sich um eine einfache Projektion

handelt

▪ Eine Zeichenkette mit dem Ausdruck des Feldes

18.07.2018 SQLScript für BW-Berater 8

SELECT id,

plan_aufwand - ist_aufwand AS restschaetzung,

(100-fertigstellung) / 100 * plan_aufwand

FROM aufgaben

Brandeis ConsultingFeldnamen einer Abfrage – Beispiel

18.07.2018 SQLScript für BW-Berater 9

SELECT aufgaben.id,

plan_aufwand - ist_aufwand AS restschaetzung,

(100-fertigstellung) / 100 * plan_aufwand

FROM aufgaben

Brandeis ConsultingEinzelne Spalten aus Quelltabellen

Wenn der Spaltenname eindeutig ist, braucht kein Korrelationsname mit

angegeben werden

Wenn immer der Korrelationsname angegeben wird, ist der Code besser zu lesen.

18.07.2018 SQLScript für BW-Berater 10

SELECT tab.table_name, --Spalte table_name nicht eindeutig!

col.column_name

FROM m_cs_tables AS tab

INNER JOIN m_cs_columns AS col

ON tab.table_name = col.table_name;

Brandeis ConsultingAlle Spalten der Quellen

Wie in ABAP kann man auch in SQLScript mit * alle Spalten aller Quellen

übernehmen. Oder über den Korrelationsnamen nur alle Spalten einer Quelle:

18.07.2018 SQLScript für BW-Berater 11

SELECT t1.* ,

t2.spalte1

FROM tabelle1 AS t1

JOIN tabelle2 AS t2

ON t1.key = t2.key;

Brandeis ConsultingOperatorausdrücke in der Feldliste - DEMO

18.07.2018 SQLScript für BW-Berater 12

SELECT id || ' - ' || titel AS Aufgabe,

plan_aufwand,

ist_aufwand,

round(ist_aufwand / plan_aufwand * 100, 0)

|| ' %' AS zeitverbrauch,

fertigstellung || ' %' AS fertigstellung

FROM aufgaben;

Brandeis ConsultingCASE-Ausdrücke in der Feldliste

Ein CASE-Ausdruck gibt genau eine Wert zurück. Es gibt zwei Varianten:

▪ Der einfache CASE-Ausdruck vergleicht den Wert eines Ausdrucks mit N

anderen Ausdrücken auf Gleichheit.

▪ Der komplexe CASE-Ausdruck wertet N unabhängige Bedingungen aus:

18.07.2018 SQLScript für BW-Berater 13

CASE spalte1

WHEN 'A' THEN 1

WHEN 'B' THEN 2

END AS spaltenname,

CASE

WHEN spalte1 = 'A' and spalte2 = 'X' THEN 1

WHEN spalte3 + spalte4 < 42 THEN 2

ELSE 0

END AS spaltenname,

Brandeis ConsultingCASE als IF

18.07.2018 SQLScript für BW-Berater 14

CASE WHEN wert2<>0 THEN wert1/wert2

ELSE 0

END AS division

Brandeis ConsultingFunktionsaufrufe in der Feldliste

▪ SQL-Funktionen

▪ UDFs

18.07.2018 SQLScript für BW-Berater 15

SELECT get_parcel_price(width, height, depth, weight )

FROM parcels;

SELECT id,

faelligkeit,

DAYS_BETWEEN( faelligkeit , current_date ) as overdue

FROM aufgaben;

Brandeis ConsultingAggregatausdrücke

Die Werte von mehreren Zeilen werden durch eine Aggregatfunktion

zusammengefasst. Z.B. SUM, COUNT, AVG, MAX, MIN…

Alle Spalten, die nicht aggregiert werden, müssen in der GROUP BY-Klausel

angegeben werden (dazu später mehr).

NULL wird in den Aggregaten nicht berücksichtigt. So berechnet AVG

beispielsweise den Durchschnittswert aller nicht-NULL Werte

18.07.2018 SQLScript für BW-Berater 16

Brandeis ConsultingSTRING_AGG

Die Aggregatfunktion STRING_AGG( <Ausdruck>, [<Trennzeichen>]) verkettet

Zeichenketten

18.07.2018 SQLScript für BW-Berater 17

SELECT sprache,

string_agg(team_text, ', ')

FROM team_text

GROUP BY sprache

Brandeis ConsultingUnterabfragen in der Feldliste

18.07.2018 SQLScript für BW-Berater 18

▪ Es sind nur skalare Abfragen erlaubt. D.h. das Ergebnis besteht aus einer Zeile

und einer Spalte

▪ Falls keine Zeile geliefert wird, ist das Ergebnis NULL

▪ Falls mehrere Zeilen geliefert werden, gibt es einen Laufzeitfehler

▪ Die Unterabfragen können korreliert sein. D.h. sie können sich auf Felder der

umgebenden Abfragen beziehen.

▪ Häufig kann man Unterabfragen in der Feldliste auch als Join umformulieren.

Brandeis ConsultingUnterabfragen in der Feldliste

18.07.2018 SQLScript für BW-Berater 19

SELECT

schema_name,

(SELECT

COUNT(*)

FROM tables

WHERE schema_name=schemas.schema_name)

AS table_count,

(SELECT

COUNT(*)

FROM procedures

WHERE schema_name=schemas.schema_name)

AS procedure_count,

schema_owner

FROM schemas;

Brandeis ConsultingWindow Functions

Window Functions ähneln den Aggregatfunktionen. Allerdings werden die Daten

nicht verdichtet. Es können aber Berechnungen innerhalb einer Partition

(=Gruppierung) durchgeführt werden.

Innerhalb der Partition kann es eine Sortierung geben, auf die sich die Funktionen

beziehen. Die Möglichkeiten sind sehr umfangreich. Im Folgenden dazu ein paar

Beispiele.

18.07.2018 SQLScript für BW-Berater 20

Brandeis ConsultingCOUNT als Window Function vs. Aggregat Function

18.07.2018 SQLScript für BW-Berater 21

--Aggregatfunktion COUNT

SELECT status,

COUNT(*) AS zaehler

FROM aufgaben

GROUP BY status

ORDER BY status;

--Window Function COUNT

SELECT id,

status,

COUNT(*) OVER (PARTITION BY status) AS zaehler

FROM aufgaben

ORDER BY id;

Brandeis ConsultingWindow Functions – Beispiele (1/3)

Zu jeder Aufgabe pro Bearbeiter den Vorgänger in Bezug auf Fälligkeit finden:

18.07.2018 SQLScript für BW-Berater 22

SELECT

BEARBEITER,

ID,

LAG(ID) OVER (PARTITION BY BEARBEITER ORDER BY FAELLIGKEIT) AS VORGAENGER

FROM AUFGABEN

ORDER BY BEARBEITER

Brandeis ConsultingWindow Functions – Beispiele (2/3)

Zu jeder Aufgabe die Anzahl der Vorgänger-Aufgaben für diesen Bearbeiter

ermitteln:

18.07.2018 SQLScript für BW-Berater 23

SELECT

bearbeiter,

id,

count(*) OVER (PARTITION BY bearbeiter ORDER BY faelligkeit) AS "#Vorgänger"

FROM aufgaben

ORDER BY bearbeiter,

faelligkeit

Brandeis ConsultingWindow Functions – Beispiele (3/3)

Der Planaufwand in Summe vor jeder Aufgabe und nach jeder Aufgabe pro

Bearbeiter:

18.07.2018 SQLScript für BW-Berater 24

SELECT

BEARBEITER,

ID,

FAELLIGKEIT,

PLAN_AUFWAND,

SUM(PLAN_AUFWAND) OVER (PARTITION BY BEARBEITER

ORDER BY FAELLIGKEIT

ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS INCL_DAVOR,

SUM(PLAN_AUFWAND) OVER (PARTITION BY BEARBEITER

ORDER BY FAELLIGKEIT

ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING )

- PLAN_AUFWAND

AS DANACH

FROM AUFGABEN

ORDER BY BEARBEITER,

FAELLIGKEIT

Brandeis ConsultingWindow Functions - Arten

▪ Aggregation – SUM, MAX, MIN, MEDIAN usw.

▪ Rang / Platznummer in der Partition gemäß Sortierung RANK, DENSE_RANK

▪ Position in der Partition (eindeutig im gegensatz zu RANK) – ROW_NUMBER

▪ Einzelner Datensatz davor oder danach, auch mit OFFSET – LAG und LEAD

▪ Statistische Funktionen für Glättung von Zahlenreihen oder den gleitenden

Durchschnitt

18.07.2018 SQLScript für BW-Berater 25

Brandeis ConsultingWindow Functions - Anmerkungen

▪ Window Functions werden immer auf der Row-Engine ausgeführt

18.07.2018 SQLScript für BW-Berater 26

Brandeis ConsultingFROM-Klausel

SELECT ... FROM <Tabellenausdruck>

Der Tabellenausdruck ist entweder:

▪ Datenbanktabellen, Tabellenvariablen oder Views

▪ Joins

▪ Tabellen-UDFs

▪ Unterabfragen

▪ Mit UNNEST aufgelöste Arrays

18.07.2018 SQLScript für BW-Berater 27

Brandeis ConsultingTabellenausdrücke

Tabellenausdrücke können auch wiederum Tabellenausdrücke enthalten:

SELECT *

FROM

(SELECT id,

status

FROM aufgaben)

AS a

LEFT OUTER JOIN

(SELECT id,

status_text

FROM status_text

WHERE sprache = 'DE' )

AS st

ON a.status = st.id

18.07.2018 SQLScript für BW-Berater 28

Brandeis ConsultingFROM Datenbanktabelle, Tabellenvariable oder View

▪ Einfache Notation nach Möglichkeit

▪ BW-Tabellen müssen in der speziellen Notation "/BIC/AMXXD602002"

angegeben werden, da der Schrägstrich im Namensraumpräfix nicht

kompatibel mit der einfachen Notation ist.

▪ Es können auch Calculation Views verwendet werden.

18.07.2018 SQLScript für BW-Berater 29

Brandeis ConsultingFROM JOIN

Joins verbinden die Daten von zwei Tabellenausdrücken zu einem neuen

Tabellenausdruck. Der Join hat mehrere Aufgaben:

▪ Hinzufügen von Informationen aus anderen Tabellen

▪ Filtern von Datensätzen

▪ Ausmultiplizieren von Datensätzen

18.07.2018 SQLScript für BW-Berater 30

Brandeis ConsultingJOIN Arten

▪ CROSS JOIN

▪ INNER JOIN

▪ LEFT/RIGHT OUTER JOIN

▪ FULL OUTER JOIN

Interessant: http://wikis.gm.fh-koeln.de/wiki_db/index.php?n=Datenbanken.Join-

Typ-SQL#Theta-Join

18.07.2018 SQLScript für BW-Berater 31

Brandeis ConsultingCROSS JOIN

Ein Cross Join bildet das kartesische Produkt (Kreuzprodukt) von zwei

Tabellenausdrücken.

Statt dem Schlüsselwort CROSS JOIN kann auch ein Komma verwendet werden.

Das reduziert die Lesbarkeit aber erheblich.

18.07.2018 SQLScript für BW-Berater 32

SELECT ...

FROM <Tabellenausdruck1> CROSS JOIN <Tabellenausdruck2>

SELECT ...

FROM <Tabellenausdruck1> , <Tabellenausdruck2>

Brandeis ConsultingCROSS JOIN Beispiel

18.07.2018 SQLScript für BW-Berater 33

--Kreuzprodukt mit CROSS JOIN

SELECT *

FROM farben

CROSS JOIN groessen;

--Kreuzprodukt nur mit Komma in der FROM-Klausel

SELECT *

FROM farben,

groessen;

Brandeis ConsultingINNER JOIN

Beim INNER JOIN gibt es eine Join-Bedingung, die mit ON eingeleitet wird. Nur

Datensätze, die auf Grund dieser Bedingung einen Partner in der jeweils anderen

Tabelle finden, werden Teil der Ergebnismenge.

18.07.2018 SQLScript für BW-Berater 34

Brandeis ConsultingINNER JOIN – Beispiel

18.07.2018 SQLScript für BW-Berater 35

SELECT *

FROM belege AS b

INNER JOIN waehrungen AS w

ON b.waehrung = w.waehrung;

Brandeis ConsultingJOIN-Bedingungen

▪ JOIN-Bedingungen können beliebige Ausdrücke und Vergleichsoperatoren

nutzen

▪ Wenn nur auf Gleichheit von Feldern geprüft wird, spricht man von einem Equi-

Join. Dieser ist erheblich schneller, als ein Non-Equi-Join. Z.B. wenn beim

Nachlesen davon Stammdaten die Zeitdimension mit berücksichtigt werden

muss, wird der Join wesentlich langsamer.

18.07.2018 SQLScript für BW-Berater 36

Brandeis ConsultingLEFT OUTER JOIN

Alle Datensätze aus der linken Tabelle erscheinen (mindestens ein mal) in der

Ergebnismenge. Falls die JOIN-Bedingung zutrifft, werden die entsprechenden

Datensätze aus der rechten Tabelle hinzugezogen. Wo kein Treffer gefunden

wurde, werden die Felder mit NULL gefüllt.

18.07.2018 SQLScript für BW-Berater 37

Brandeis ConsultingLEFT OUTER JOIN - Beispiel

18.07.2018 SQLScript für BW-Berater 38

SELECT *

FROM belege AS b

LEFT OUTER JOIN waehrungen AS w

ON b.waehrung = w.waehrung

Brandeis ConsultingRIGHT OUTER JOIN

Wie LEFT OUTER JOIN, nur mit vertauschten Rollen…

18.07.2018 SQLScript für BW-Berater 39

SELECT *

FROM belege AS b

RIGHT OUTER JOIN waehrungen AS w

ON b.waehrung = w.waehrung

Brandeis ConsultingFULL OUTER JOIN

Alle Datensätze von beiden Tabellen werden in der Ergebnismenge auftauchen.

18.07.2018 SQLScript für BW-Berater 40

Brandeis ConsultingJOIN CARDINALITY (HANA 2.0 SPS03)

The join cardinality gives a hint to the SQL processing for better performance.

Incorrect cardinalities can lead to incorrect results.

Syntax:

SELECT … FROM <table1>

[INNER|[LEFT|RIGHT]OUTER] [<left side> TO <right side>] JOIN <table2>

Allowed values at both sides:

▪ MANY – 0..N

▪ ONE – 0..1

▪ EXACT ONE – 1

Blog von Jan Zwickel: https://blogs.sap.com/2017/10/27/join-cardinality-setting-in-calculation-views/

18.07.2018 SQLScript für BW-Berater 41

Brandeis ConsultingWHERE und ON-Bedingungen

▪ WHERE und ON-Bedingung können jeweils die Datenmenge einschränken.

▪ Diese Einschränkungen werden zu unterschiedlichen Zeitpunkten ausgewertet:

▪ Die Einschränkungen der ON-Bedingung werden schon vor dem Ausführen des Joins

berücksichtigt

▪ Einschränkungen der WHERE-Bedingung werden erst nach der Ausführung des Joins

berücksichtigt.

▪ Nach Möglichkeit in der ON-Bedingung einschränken.

18.07.2018 SQLScript für BW-Berater 42

Brandeis ConsultingWHERE und ON-Bedingungen - Beispiel

18.07.2018 SQLScript für BW-Berater 43

SELECT * FROM belege

LEFT OUTER JOIN waehrungen

ON belege.waehrung = waehrungen.waehrung

where waehrungen.waehrung <> 'EUR';

SELECT * FROM belege

LEFT OUTER JOIN waehrungen

ON belege.waehrung = waehrungen.waehrung

and waehrungen.waehrung <> 'EUR';

Brandeis ConsultingTabellen-UDFs

Als Tabellenausdrücke in der FROM-Klausel sind auch Funktionen erlaubt.

Demo:

select * from udf_statustexte( 'DE');

18.07.2018 SQLScript für BW-Berater 44

Brandeis ConsultingUnterabfragen in der FROM-Klausel

Gelegentlich findet man auch Unterabfragen in einer FROM-Klausel. Das ist vor

allem dann praktisch, wenn man nicht im Kontext von SQLScript ist.

In SQLScript kann man statt der Unterabfrage vorher ein entsprechende

Tabellenvariable definieren…

18.07.2018 SQLScript für BW-Berater 45

Brandeis ConsultingUnterabfragen in der FROM-Klausel & Alternative

18.07.2018 SQLScript für BW-Berater 46

SELECT bearbeiter,

todo

FROM ( SELECT bearbeiter,

SUM(plan_aufwand - ist_aufwand) as todo

FROM aufgaben

GROUP BY bearbeiter )

ORDER BY todo;

DO BEGIN

lt_todo = SELECT bearbeiter,

SUM(plan_aufwand - ist_aufwand) as todo

FROM aufgaben

GROUP BY bearbeiter;

SELECT bearbeiter,

todo

FROM :lt_todo

ORDER BY todo;

END;

Brandeis ConsultingWHERE-Klausel

Mit der WHERE-Klausel werden die Daten einer Abfrage eingeschränkt. Darin

können mehrere, mit logischen Operatoren AND, OR und NOT verknüpfte

Bedingungen vorkommen.

18.07.2018 SQLScript für BW-Berater 47

Brandeis ConsultingKomponenten der WHERE Klausel

Vergleichsausdrücke

• Typisch: Vergleich einer Spalte mit einem Literal

• Theoretisch jeder beliebige Ausdruck im Vergleich möglich

• Auch eine korrelierte Unterabfrage ist für den Vergleichswert möglich

IN/SOME/ANY/ALL Prädikat

• Vergleich eines Ausdrucks mit einer Menge von Werten

• Die Wertemenge kann auch aus einer Unterabfrage kommen

EXISTS Prädikat

• Unterabfrage, die entscheidet, ob ein Datensatz in der Ergebnismenge ist oder nicht.

Vergleich mit einem Muster: LIKE

• Platzhalter % für 0-N Zeichen, _ für genau ein Zeichen

• Mit LIKE_REGEXPR kann auch nach regulären Ausdrücken gesucht werden

WHERE Klausel

18.07.2018 SQLScript für BW-Berater 48

Brandeis ConsultingVergleich mit einzelnen Ausdrücken

Meist werden in der WHERE-Klausel Bedingungen der Form

SPALTE = Konstante

formuliert. Grundsätzlich sind aber bei einem Vergleich links und rechts vom

Gleicheitsszeichen beliebige Ausdrücke erlaubt. Z.B.

DAYS_BETWEEN( faelligkeit, current_date )

> plan_aufwand - ist_aufwand

18.07.2018 SQLScript für BW-Berater 49

Brandeis ConsultingVergleich mit mehreren Werten

Mit ANY/SOME bzw. ALL nach dem Vergleichsoperator, kann der Vergleich mit

einer ganzen Liste von Werten erfolgen.

Die Werte werden entweder als Liste in Klammern angegeben, oder von einer

Unterabfrage geliefert.

18.07.2018 SQLScript für BW-Berater 50

Brandeis ConsultingVergleich mit mehreren Werten – Beispiele

18.07.2018 SQLScript für BW-Berater 51

SELECT *

FROM aufgaben

WHERE STATUS = ANY ( 1, 2, 4 );

SELECT *

FROM aufgaben

WHERE STATUS = ANY ( SELECT id

FROM STATUS

WHERE is_final = true );

SELECT *

FROM aufgaben

WHERE STATUS <> ALL ( SELECT id

FROM STATUS

WHERE is_final = true );

Brandeis ConsultingVergleich mit einem Muster

Mit dem LIKE-Prädikat können Sie ein Muster in einer Zeichenkette suchen. Mit

NOT kann LIKE negiert werden. Platzhalter sind:

▪ Das Prozentzeichen % für eine beliebige Anzahl (0-N) von beliebigen Zeichen

▪ Der Unterstrich _ für exakt ein beliebiges Zeichen

18.07.2018 SQLScript für BW-Berater 52

--1. Negierung des ganzen Prädikats

SELECT count(*)

FROM aufgaben

WHERE NOT ( titel LIKE '%Aliquam%' );

--2. Äquivalente Abfrage mit NOT LIKE

SELECT count(*)

FROM aufgaben

WHERE titel NOT LIKE '%Aliquam%';

Brandeis Consulting

▪ select * from tables where table_name like '%DS!_TC%' escape '!'

18.07.2018 SQLScript für BW-Berater 53

Brandeis ConsultingVergleich mit einem Intervall

Das BETWEEN Prädikat prüft, ob ein Wert innerhalb eines abgeschlossenen

Intervalls liegt. Das bedeutet, dass die Werte von Ober- und Untergrenze zu

dem Intervall dazugehören.

18.07.2018 SQLScript für BW-Berater 54

Brandeis ConsultingVergleich mit einer Menge

Das IN-Prädikat ähnelt dem Vergleich mit ANY/SOME. Es wird geprüft, ob eine

Spalte in einer Menge von Werten ist. Diese kann wieder als Liste oder als

Unterabfrage formuliert werden.

18.07.2018 SQLScript für BW-Berater 55

--1. Abfrage für eine Spalte mit mehreren Werten mit OR

SELECT *

FROM benutzer

WHERE vorname = 'Aldo'

OR vorname = 'Olag'

OR vorname = 'Sascha';

--2. Analoge Abfrage mit dem IN-Prädikat

SELECT *

FROM benutzer

WHERE vorname IN ( 'Aldo', 'Olag','Sascha' );

Brandeis ConsultingVergleich mit einer Menge – Beispiele

18.07.2018 SQLScript für BW-Berater 56

--1. Abfrage für eine Spalte mit mehreren Werten mit OR

SELECT *

FROM benutzer

WHERE vorname = 'Aldo'

OR vorname = 'Elvin'

OR vorname = 'Sascha';

--2. Analoge Abfrage mit dem IN-Prädikat

SELECT *

FROM benutzer

WHERE vorname IN ( 'Aldo', 'Elvin', 'Sascha' );

--3. Nutzung einer Unterabfrage mit dem IN-Prädikat:

-- Benutzer, denen aktuell keine Aufgabe zugeordnet ist

SELECT *

FROM benutzer

WHERE id NOT IN ( SELECT DISTINCT bearbeiter

FROM aufgaben );

Das sieht man häufig in ABAP…

Brandeis ConsultingPrüfung auf Existenz

Mit dem EXISTS-Prädikat kann geprüft werden, ob eine korrelierte Unterabfrage

ein Ergebnis (d.h. mindestens eine Zeile) liefert oder nicht.

18.07.2018 SQLScript für BW-Berater 57

Brandeis ConsultingPrüfung auf Existenz – Beispiele

18.07.2018 SQLScript für BW-Berater 58

--1. Abfrage mit EXISTS-Prädikat - Alle Benutzer mit mindestens einer Aufgabe

SELECT *

FROM benutzer

WHERE EXISTS (

SELECT bearbeiter

FROM aufgaben

WHERE aufgaben.bearbeiter = benutzer.id );

--2. Abfrage mit NOT EXISTS - Aufgaben, deren Status nicht in der Statustabelle steht

SELECT *

FROM aufgaben

WHERE NOT EXISTS (

SELECT id

FROM STATUS

WHERE STATUS.id = aufgaben.STATUS );

--3. Analoge Abfrage mit NOT IN

SELECT *

FROM aufgaben

WHERE STATUS NOT IN (

SELECT id

FROM STATUS );

Brandeis ConsultingUnterschied EXISTS und IN-Prädikat

In den Beispielen haben wir gesehen, dass manche Bedingungen mit beiden

Prädikaten formuliert werden können.

Das IN-Prädikat setzt voraus, dass aus der Unterabfrage auch der entsprechende

Spaltenwert geliefert werden kann. Bei EXISTS reicht die Existenz einer Zeile aus.

Das EXISTS-Prädikat kann auch mehrere Spalten vergleichen, IN bezieht sich

immer nur auf eine Spalte.

18.07.2018 SQLScript für BW-Berater 59

Brandeis ConsultingPrüfung auf NULL

Mit

<Ausdruck> IS [NOT] NULL

kann geprüft werden, ob ein Ausdruck, insbesondere eine Tabellenspalte, den

Wert NULL hat. Diese Abfrage ist mit dem normalen Vergleichsprädikaten nicht

möglich.

18.07.2018 SQLScript für BW-Berater 60

Brandeis ConsultingSonstige Bedingungen in der WHERE-Klausel

▪ In der WHERE –Klausel kann auch mit CASE eine Fallunterscheidung

stattfinden. Z.B. anhand eines Parameters

▪ Mit CONTAINS kann auf Spalten in Column Tables unscharf gesucht werden.

18.07.2018 SQLScript für BW-Berater 61

Brandeis ConsultingÜbung Joins

▪ Welche Aufgaben sind in einem finalen Status?

18.07.2018 SQLScript für BW-Berater 62

Brandeis ConsultingÜbungen – Lösung

18.07.2018 SQLScript für BW-Berater 63

DO BEGIN

SELECT *

FROM aufgaben

INNER JOIN status

ON aufgaben.status = status.id

WHERE status.is_final = TRUE;

END;

Brandeis ConsultingGROUP BY Klausel

Wenn Aggregat-Funktionen verwendet werden, so muss nach allen nicht-

Aggregat-Spalten mit GROUP BY gruppiert werden. Damit wird die Granularität

der Aggregation festgelegt.

Feldliste und GROUP BY-Klausel müssen exakt zueinander passen.

18.07.2018 SQLScript für BW-Berater 64

SELECT bearbeiter,

COUNT(*) AS anzahl

FROM aufgaben

GROUP BY bearbeiter;

Brandeis ConsultingGROUP BY mit Ausdrücken

Falls einzelne Spalten in

der Feldliste mit einem

Ausdruck definiert wurden,

so muss sich dieser

Ausdruck in der GROUP BY-

Klausel entsprechend

wiederholen.

18.07.2018 SQLScript für BW-Berater 65

SELECT CASE

WHEN faelligkeit < to_date('2017-12-01')

AND status NOT IN ( 5, 6 )

THEN 'zu pruefen'

ELSE 'OK'

END AS "Prüfen?",

count(*) AS cnt

FROM aufgaben

GROUP BY CASE

WHEN faelligkeit < to_date('2017-12-01')

AND status NOT IN ( 5, 6 )

THEN 'zu pruefen'

ELSE 'OK'

END;

Brandeis ConsultingGROUP BY in 2-Stufen

Weitere Alternative: Als mehrstufige Abfrage, siehe Folien zu Unterabfragen

18.07.2018 SQLScript für BW-Berater 66

DO BEGIN

--1. Neue Spalte mit CASE-Ausdruck erzeugen

lt_select = SELECT CASE

WHEN faelligkeit < to_date('2017-12-01')

AND status NOT IN ( 5, 6 )

THEN 'zu pruefen'

ELSE 'OK'

END AS "Prüfen?"

FROM aufgaben;

--2. Gruppierung nach der neuen Spalte

SELECT "Prüfen?",

count(*) as cnt

FROM :lt_select

GROUP BY "Prüfen?";

END

Brandeis ConsultingGROUP BY – GROUPING SETS

Für BW-Entwicklung sind GROUPING SETS nicht relevant. Sie erlauben in

Abfragen die Gruppierung nach mehreren Kriterien gleichzeitig.

18.07.2018 SQLScript für BW-Berater 67

Brandeis ConsultingHAVING Klausel

▪ Bildet einen Filter auf die aggregierten Daten

▪ Wird erst nach der Aggregation ausgewertet

▪ Sollte nur verwendet werden, wenn sich das Kriterium nicht schon vorher mit

WHERE filtern lässt

▪ Die HAVING Klausel muss sich auf die Ausdrücke der Feldliste beziehen, nicht

auf die Spaltennamen:

18.07.2018 SQLScript für BW-Berater 70

SELECT bearbeiter,

COUNT(*) AS anzahl

FROM aufgaben

GROUP BY bearbeiter

HAVING COUNT(*) > 50;

Brandeis ConsultingORDER BY Klausel

Die Reihenfolge der Datensätze einer SELECT-Abfrage wird durch die ORDER BY-

Klausel festgelegt. Im Gegensatz zur GROUP BY, HAVING oder WHERE-Klausel

kann man sich hier aber auf die Spaltennamen beziehen:

Ohne ORDER BY-Klausel werden die Datensätze in zufälliger Reihenfolge

zurückgegeben.

18.07.2018 SQLScript für BW-Berater 71

SELECT bearbeiter,

COUNT(*) AS anzahl

FROM aufgaben

GROUP BY bearbeiter

HAVING COUNT(*) > 50

ORDER BY anzahl;

Brandeis ConsultingORDER BY mit sonstigen Ausdrücken

Die Sortierung mit ORDER BY kann sich aber auch auf beliebige andere Ausdrücke

beziehen. Auch auf solche, die nicht in der Feldliste vorhanden sind.

18.07.2018 SQLScript für BW-Berater 72

SELECT id,

titel

FROM aufgaben

ORDER BY plan_aufwand - ist_aufwand;

Brandeis ConsultingORDER BY mit Spaltennummern

Die Sortierung mit ORDER BY kann sich auch auf die Spaltennummern beziehen.

Das ist aber keine gute Idee, da es bei Änderungen an der Abfrage sehr

fehlerträchtig ist. Das gilt insbesondere in Kombination mit dem * in der Feldliste.

18.07.2018 SQLScript für BW-Berater 73

SELECT id,

titel

FROM aufgaben

ORDER BY 2, 1;

Brandeis ConsultingORDER BY – Zusätze zum Sortierausdruck

Nach einem Sortierausdruck können die folgenden Zusätze angegeben werden:

▪ ASC – Aufsteigende Sortierung (Standard)

▪ DESC – Absteigende Sortierung

▪ NULLS FIRST – NULL-Werte werden als kleinster Wert betrachtet (Standard)

▪ NULLS LAST – NULL-Werte werden als größter Wert betrachtet

18.07.2018 SQLScript für BW-Berater 74

Brandeis ConsultingMengenlehre

Wenn zwei SELECT-Abfragen die gleichen Spalten haben, dann kann man damit

Mengenoperationen durchführen. Zur Verfügung stehen die folgenden

Operatoren:

▪ Vereinigungsmenge (UNION)

▪ Schnittmenge (INTERSECT)

▪ Subtraktion von Mengen (EXCEPT)

18.07.2018 SQLScript für BW-Berater 75

Brandeis ConsultingMengenoperatoren Allgemein

Die Syntax zur Verwendung der Mengenoperatoren sieht so aus:

<Abfrage1> <Mengenoperator> <Abfrage2>

Alle Abfragen brauchen eine kompatible Spaltenstruktur:

▪ Der Datentyp und der Spaltenname wird aus der ersten Abfrage übernommen

▪ Der Inhalt der Spalten der zweiten Abfrage muss kompatibel sein

▪ Die Spaltennamen der zweiten Abfrage spielen keine Rolle

18.07.2018 SQLScript für BW-Berater 76

Brandeis ConsultingUNION

UNION ist der bekannteste Mengenoperator und kann nicht durch andere Tricks

ersetzt werden. Er führt die Ergebnisse von zwei Abfragen mit gleicher

Spaltenstruktur zusammen.

Mit UNION ALL wird erreicht, dass gegebenenfalls Duplikate erhalten bleiben,

wenn beispielsweise ein Datensatz in beiden Abfragen vorkommt.

Alle Mengenoperatoren, außer UNION ALL, entfernen alle Duplikate!

18.07.2018 SQLScript für BW-Berater 77

Brandeis ConsultingUNION – Beispiel

18.07.2018 SQLScript für BW-Berater 78

--Abfrage mit UNION: Duplikate werden entfernt

SELECT 'A' AS SPALTE1,

'B' AS SPALTE2

FROM DUMMY

UNION

SELECT 'A' AS SPALTE1A,

'B' AS SPALTE2A

FROM DUMMY;

--Zweite Abfrage mit UNION ALL ohne Duplikatsentfernung

SELECT 'A' AS spalte1,

'B' AS spalte2

FROM DUMMY

UNION ALL

SELECT 'A' AS spalte1,

'B' AS spalte2

FROM DUMMY;

Brandeis ConsultingINTERSECT

Die Schnittmenge von zwei Abfragen wird mit dem Mengenoperator INTERSECT

gebildet. In der Praxis sieht man diesen Operator relativ selten, da man das

gleiche Ergebnis häufig auch mit einem Inner-Join auf geeignete Schlüsselfelder

erreichen kann.

Vorteil von INTERSECT: Es werden immer alle Spalten berücksichtigt.

18.07.2018 SQLScript für BW-Berater 79

Brandeis ConsultingINTERSECT – Beispiel

18.07.2018 SQLScript für BW-Berater 80

--Abfrage aller Benutzer, die Projektleiter sind und eine

--Aufgabe zur Bearbeitung zugewiesen haben.

--Zunächst mit INTERSECT:

SELECT bearbeiter

FROM aufgaben

INTERSECT

SELECT projektleiter

FROM projekte;

--Und als INNER JOIN:

SELECT DISTINCT bearbeiter

FROM aufgaben

INNER JOIN projekte

ON bearbeiter = projektleiter;

Brandeis ConsultingEXCEPT

Um eine Ergebnismenge von einer anderen Ergebnismenge abzuziehen, kann der

EXCEPT-Mengenoperator verwendet werden. Dieser Operator wird in der Praxis

eher selten verwendet, da die Mengensubtraktion auch mit dem NOT EXISTS-

Prädikat abgebildet werden kann.

18.07.2018 SQLScript für BW-Berater 81

Brandeis ConsultingEXCEPT – Beispiel

18.07.2018 SQLScript für BW-Berater 82

--Abfrage aller Bearbeiter von Aufgaben, ohne Projektleiter

--Zunächst mit EXCEPT

SELECT bearbeiter

FROM aufgaben

EXCEPT

SELECT projektleiter

FROM projekte;

--Und die gleiche Abfrage mit NOT EXISTS

SELECT DISTINCT bearbeiter

FROM aufgaben AS a

WHERE NOT EXISTS (

SELECT id

FROM projekte AS p

WHERE p.projektleiter = a.bearbeiter );

Brandeis ConsultingUnterabfragen

Abfragen, die als Ausdruck in anderen SQL-Anweisungen verwendet werden,

nennen wir Unterabfragen (Subqueries).

18.07.2018 SQLScript für BW-Berater 83

Brandeis ConsultingSkalare Unterabfragen

Skalare Unterabfrage liefern genau einen Wert:

18.07.2018 SQLScript für BW-Berater 84

SELECT *

FROM aufgaben

WHERE faelligkeit = (SELECT MAX(faelligkeit)

FROM aufgaben);

Brandeis ConsultingSpalten-Unterabfragen

Skalare Unterabfrage liefern eine Tabelle mit genau einer Spalte:

Es kann sein, dass die Treffermenge der Unterabfrage leer ist.

18.07.2018 SQLScript für BW-Berater 85

SELECT *

FROM aufgaben

WHERE status IN (SELECT id

FROM status

WHERE is_final = TRUE);

Brandeis ConsultingTabellen-Unterabfragen

Tabellen-Unterabfrage liefern eine Tabelle, die man überall dort verwenden kann,

wo ein Tabellenausdruck erforderlich ist.

Z.B. mehrstufige Abfragen statt Tabellenvariablen, vgl. GROUP BY Folie…

18.07.2018 SQLScript für BW-Berater 86

SELECT "Prüfen?",

count(*)

FROM ( SELECT CASE

WHEN faelligkeit < to_date('2017-12-01')

AND status NOT IN ( 5, 6 )

THEN 'zu pruefen'

ELSE 'OK'

END AS "Prüfen?",

id

FROM aufgaben)

GROUP BY "Prüfen?";

Brandeis ConsultingKorrelierte Unterabfragen

Eine Unterabfrage, die sich auf die Spalten einer umgebenden Abfrage bezieht,

bezeichnet man als korrelierte Unterabfrage.

18.07.2018 SQLScript für BW-Berater 87

SELECT bearbeiter,

faelligkeit,

id,

titel

FROM aufgaben AS a

WHERE faelligkeit = (SELECT MAX(faelligkeit)

FROM aufgaben

WHERE bearbeiter = a.bearbeiter)

ORDER BY faelligkeit DESC,

bearbeiter ASC;

Brandeis ConsultingAliasnamen

Sowohl Spalten als auch Tabellen können mit AS in Abfragen einen neuen Namen

verpasst bekommen.

▪ Spaltenalias geben einer Spalte einen neuen Namen. Dieser ist für den

Aufurfer der Abfrage sichtbar.

▪ Tabellenalias geben einem Tabellenausdruck in der FROM-Klausel innerhalb

einer Abfrage einen Namen. Das kann erforderlich sein, wenn der

Tabellenname ansonsten nicht eindeutig ist, z.B. wenn eine Tabelle doppelt in

einer Abfrage vorkommt.

18.07.2018 SQLScript für BW-Berater 88

Brandeis ConsultingVorteile von Alias Namen

▪ Bessere Lesbarkeit des Codes

▪ Lange oder sehr technische Tabellenamen können ersetzt werden

▪ Der Name einer Tabelle kann die Rolle der Tabelle statt dem Inhalt repräsentieren:

▪ Bearbeiter statt Benutzer oder

▪ Projektleiter statt Benutzer

▪ Ein Austausch von Tabellen in Abfragen ist möglich

18.07.2018 SQLScript für BW-Berater 89

Brandeis ConsultingBeispiel für Aliasnamen

18.07.2018 SQLScript für BW-Berater 90

SELECT aufgaben.id AS aufgabe_id,

aufgaben.titel AS aufgabe_titel,

bearbeiter.id AS bearbeiter_id,

bearbeiter.vorname

|| ' '

|| bearbeiter.nachname AS bearbeiter_name,

projektleiter.id AS projektleiter_id,

projektleiter.vorname

|| ' '

|| projektleiter.nachname AS projektleiter_name

FROM aufgaben

INNER JOIN projekte

ON aufgaben.projekt = projekte.id

INNER JOIN benutzer AS projektleiter

ON projekte.projektleiter = projektleiter.id

INNER JOIN benutzer AS bearbeiter

ON aufgaben.bearbeiter = bearbeiter.id;