# SQL-Abfragen verbinden



## Muppes (20. August 2013)

Hallo zusammen,
bin immer noch SQL-Grünschnabel, daher folgende Frage an die Experten:

Ich arbeite in einer Bibliothek. Dort gibt es unterschiedliche Mediengruppen (Sachliteratur, Romane, DVDs usw.).

Das kann ich:
z.B.:
"select d01bestandsgruppe, count (*) d01ex from d01buch group by d01bestandsgruppe"
liefert:
d01bestandsgruppe          d01ex
Sachliteratur                    15.200
Romane                             8.500
usw.
(d01ex = Anzahl der vorhandenen Medien)
krieg das leider hier nicht richtig formatiert:
1. Spalte: Überschrift: Bestandsgruppe, darunter: 1. Zeile: Sachliteratur, 2. Zeile: Romane usw, dahinter jeweils die Anzahl der Medien

Erweitere ich obiges Kommando:
z.B.:
"select d01bestandsgruppe, count (*) d01ex from d01buch group by d01bestandsgruppe where d01status="entliehen" erhalte ich statt der Spalte d01ex mit der Anzahl aller vorhandenen Medien der jeweiligen Gruppe jetzt die Spalte d01status mit der Anzahl der zur Zeit entliehenen Medien dieser Bestandsgruppe

Das kann ich (leider) nicht:
Ich möchte bdeide Abfragen in einer, also:
1. Spalte: Bestandsgruppe
2. Spalte: Anzahl aller Exemplare in dieser Bestandsgruppe
3. Spalte: Anzahl aller ENTLIEHENEN Exemplare dieser Bestandsgruppe (also d01status="entliehen")

Wie lässt sich das in EINER Abdrage bewerkstelligen?

Hoffe, einer weiß das...
Herzlichen Dnak schon mal für die Bemühungen.

Viele Grüße
Muppes


----------



## tombe (20. August 2013)

Eventuell kannst du es über eine UNION SELECT Abfrage lösen, was anders fällt mir sonst nicht ein.


```
SELECT
    COUNT(*) AS menge
FROM tabelle
UNION
SELECT
    COUNT(*) AS menge
FROM tabelle
WHERE bedingung = 'ABC'
```

Liefert dir dann zwei Datensätze zurück. Der erste enthält die Gesamtmenge und der zweite die Anzahl auf die die Bedingung(en) zutreffen.

*NACHTRAG:* Geht auch noch anders.


```
SELECT
    CONUT(*) as gesamt,
    SUM(CASE WHEN bedingung = 'ABC' THEN 1 ELSE 0 END) AS teil
FROM tabelle
```

Hiermit bekommst du einen Datensatz zurück und die Wete sind auf die Felder "gesamt" und "teil" verteilt.


----------



## Muppes (20. August 2013)

Hallo Tombe,
vielen Dank für Deine Bemühungen. Komme aber noch nicht klar damit. Kannst Du das mal in eine Abfrage bezogen auf mein Problem umwandeln?  Hab's probiert, aber leider bislang erfolglos.
Zum genaueren Verständnis siehe angehängtes Dokument.
Herzlichen Dank.


----------



## tombe (20. August 2013)

So mal auf die Schnelle:


```
SELECT
    d01mart,
    COUNT(*) AS gesamt,
    SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END) AS verliehen,
    d01gsi FROM d01buch
WHERE d01mtyp = 1
GROUP BY d01mart
```

Um was für eine Datenbank handelt es sich eigentlich mySQL? Dann könntest du die vielleicht hier einstellen (zumindest Teile davon) damit man es auch gleich testen kann.

Welchen Prozentwert willst du berechnen. Wieviele der Bücher zur Zeit verliehen sind?


----------



## Muppes (20. August 2013)

Hallo Tombe,

hat leider nicht geklappt. Folgende Fehlermeldung:
Fehler: Can't execute select :"SELECT 
d01mart, 
COUNT(*) AS gesamt, 
SUM(WHEN CASE d01status = 4 THEN 1 ELSE 0 END) AS verliehen, 
d01gsi FROM d01buch 
WHERE d01mtyp = 1 
GROUP BY d01mart". Server message number=156 severity=15 state=2 line=4 server=sisisSYB text=Falsche Syntax bei Schlüsselwort 'WHEN'.

Was den Prozentwert anbelangt, ja, genau das möchte ich.
Welches sql kann ich dir leider nicht sagen. Es ist aber kein mysql.

Herzlichen Dank & Grüße
Muppes


----------



## MPr (20. August 2013)

vielleicht:


```
SELECT
    d01mart,
    COUNT(*) AS gesamt,
    SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END) AS verliehen,
    d01gsi FROM d01buch
WHERE d01mtyp = 1
GROUP BY d01mart
```


----------



## Muppes (21. August 2013)

Hallo MPr,

das war's fast. Musste in drittletzter Zeile noch ein zusätzliches COUNT einbauen:
SELECT
    d01mart,
    COUNT(*) AS gesamt,
    SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END) AS verliehen,
    COUNT(*) d01gsi FROM d01buch
WHERE d01mtyp = 1
GROUP BY d01mart

Das führt zu folgender Anzeige, in der die gewünschten Infos vorhanden sind, die 4. Spalte aber überflüssig ist (Zeilen leider verschoben, aber erkennbar, was ich meine)
d01mart gesamt verliehen d01gsi 
20 117 6 117 
21 624 113 624 
22 2061 570 2061 
23 275 15 275 
24 1061 58 1061 

Statt der jetzigen 4. Spalte wäre der prozentuale Anteil interessant, z.B. in 2. Zeile 113 von 624 Titeln entliehen = 18,1%.

Wie ist das möglich?
Und: Kann mir jemand eine guten Link posten, in dem die Kommandos AS und CASE plausibel erklärt sind?

Ganz herzlichen Dank für Euer Engagement. Große Klasse!

Viele Grüße
Muppes


----------



## tombe (21. August 2013)

Also wozu du den zweiten COUNT brauchst, ist mir nicht klar.

*AS* wird je nach Datenbanktyp benötigt um einen gültigen Feldbezeichner zu vergeben.

*CASE WHEN* kann man vielleicht mit "wenn der Fall eintritt das" übersetzen. In diesem Beispiel: Wenn der Fall eintritt das d01status = 1 ist dann zähle 1 dazu sonst (ELSE) 0 bzw. nichts. Das END schließt das dann einfach noch ab.

*%* bekommst du wenn du

```
... (COUNT(*) / SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END)) AS prozent ...
```
in die Abfrage aufnimmst.


----------



## Muppes (22. August 2013)

Hallo Tombe,
herzlichen Dank für die Infos.

Wenn ich das zusätzliche COUNT nicht aufnehme, kommt sowas:
d01mart gesamt verliehen d01gsi 
21 624 114 0421255 
40 1449 239 0515594 
41 1320 114 3042272 
21 624 114 0484144 
32 880 85 0570845 
35 242 12 0000721 
24 1061 58 0556749 
31 643 59 0448792 
38 1163 212 0504464 
28 350 30 0001042 
28 350 30 0001053 
usw.

Es wird also jeder Datensatz EINZELN aufgeführt, also z.B. aud der Bestandsgruppe 28 nicht die Gesamtsumme aller Titel, sondern für jeden Datensatz eine Zeile.

Was den Prozentwert anbelangt:
Kannst Du mir die komplette Abfrage reinstellen. Irgendwie funktioniert der Befehl bei mir nicht.

Vorab schon mal wieder ganz vielen Dank.

Das mit AS und CASE THEN habsch jetzt verstanden. Wieder was gelernt!
Scheint so ähnlich wie der EXCEL-Befehl "ZÄHLENWENN" zu sein.

Grüße
vom Muppes


----------



## tombe (22. August 2013)

Hallo Muppes,

das mit dem COUNT verstehe ich noch immer nicht und es ist echt schwer deine Beispiele zu lesen wenn sie nicht formatiert und mit Kommentaren versehen sind was sie bedeuten.

Die Abfrage mit Ausgabe der Prozentwerte sollte bei dir wohl so aussehen:


```
SELECT
    d01mart,
    COUNT(*) AS gesamt,
    SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END) AS verliehen,
    (COUNT(*) / SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END)) AS prozent,
    COUNT(*) AS zusatz
FROM d01buch
WHERE d01mtyp = 1
GROUP BY d01mart
```

Viele Grüße Thomas


----------



## Muppes (23. August 2013)

Hallo Tombe,
vielen Dank für Deinen Beitrag.
Die Prozentwerte werden ao allerdings falsch berechnet. Ich habe das Kommando umgestellt/ergänzt:

                Code sql:

1
2
3
4
5
6
7
8
9
*SELECT*
    d01mart,
*COUNT*(*) *AS* gesamt,
*SUM*(*CASE* *WHEN* d01status = 4 *THEN* 1 *ELSE* 0 *END*) *AS* verliehen,
(*SUM*(*CASE* *WHEN* d01status = 4 *THEN* 1 *ELSE* 0 *END*) * 100 / *COUNT*(*)) *AS* prozent,
*COUNT*(*) *AS* zusatz
*FROM* d01buch
*WHERE* d01mtyp = 1
*GROUP* *BY* d01mart





Ich bräuchte jetzt aber bei den Prozenten noch mindestens 1 Hinterkommastelle ******

Und mir ist noch nicht die letzte Spalte klar "zusatz".
Spalte 1 "d01mart" bedeutet Medienart, also Bestandsgruppe (mart 22 ist z.B. Geographie)
Spalte 2 "gesamt" - Gesamtanzahl aller Medien in dieser Gruppe
Spalte 3 "entliehen" - Gesamtanzahl aller entliehenen Medien dieser Gruppe
Spalte 4 "prozent" - prozentualer Anteil der entliehenen Medien an der Gesamtanzahl dieser Gruppe
Spalte 5 "zusatz" - mir nicht klar. Ist die selbe Zahl wie in Spalte 2 "gesamt"


Im Anhang 2 Bilddateien:
einmal mit den falschen, einmal mit den richtigen Prozentwerten
in beiden ist auch die Spalte "zusatz" zu sehen

Herzlichen Dank vorab für die Bemühungen.
Muppes


----------



## tombe (23. August 2013)

Was die Berechnung angeht, hast du natürlich Recht. Da habe ich mal wieder schlampig geschrieben.

Die Spalte "zusatz" und die zusätzliche COUNT-Anweisung habe ich reingeschrieben, weil du in Beitrag 9 geschrieben hast das du es so brauchst (wie in Beitrag 10 zu lesen, habe ich es nicht verstanden wozu es sein soll).

Die Nachkommastellen bekommst du einfach indem du alle numerischen Werte mit FORMAT entsprechend formatierst.


----------



## Muppes (26. August 2013)

OK,
Spalte zusatz ist jetzt weg.
Aber wo genau füge ich das "FORMAT" ein. Krieg's nicht hin. Rookie halt ...


----------



## tombe (26. August 2013)

Hast du dir das Beispiel mal ein bisschen genauer angeschaut, dann sollte es doch eigentlich klar werden wie es gemeint ist.

Du schreibst nicht:

```
COUNT(*) AS gesamt,
SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END) AS verliehen
```

sondern:

```
FORMAT(COUNT(*), 2) AS gesamt,
FORMAT(SUM(CASE WHEN d01status = 4 THEN 1 ELSE 0 END), 2) AS verliehen
```

Also einfach das Feld (oder die Anweisung die den numerischen Wert ermittelt) nach FORMAT in Klammern setzten und dazu mit Komma getrennt die Nachkommastellen angeben. Im obigen Beispiel sind es immer 2 Nachkommastellen.


----------



## Muppes (26. August 2013)

Hallo Tombe,

beim FORMAT-Kommando kommt immer noch eine Fehlermeldung (s. Datei im Anhang). Offenbar wird das Kommando nicht erkannt? Einen Syntaxfehler kann ich nicht erkennen.

Grüße
Muppes


----------



## tombe (26. August 2013)

Nein nach einem Syntaxfehler sieht es wirklich nicht aus, dann kennt deine Datenbank den Befehl nicht.

Ich hatte schonmal danach gefragt um was für eine Art Datenbank es sich handelt. Wenn man das wüßte, könnte man nach einer Alternative suchen.


----------



## Muppes (27. August 2013)

Hallo,

habe jetzt alles so wie gewünscht.
Arbeite mit SQL unter Sybase ASE 15.0.3.

Abfrage wurde in diesem Fall um die Kommandos STR und ROUND ergänzt:


```
SELECT
d01mart AS SystGruppe,
COUNT(*) AS gesamt,
SUM (CASE WHEN d01status=4 THEN 1 ELSE 0 END) AS verliehen,
STR(ROUND(SUM(CASE WHEN d01status=4 THEN 1 ELSE 0 END)*100.0/COUNT(*), 2), 6, 2) AS prozent
FROM d01buch
WHERE d01mtyp=1
GROUP by d01mart
```

Mit ROUND 2 wird auf 2 Stellen gerundet.
Mit STR und 6, 2 werden nur 6 Stellen angezeigt, incl. des Kommas: max 3 vorm Komma (mehr können es ja nicht sein als Wert 100) und halt 2 hinterm Komma.

Thema jetzt abgehakt. 
Habe hier viel gelernt. 
Herzlichen Dank an alle, insbesondere Tombe (Thomas).

Grüße vom Muppes (Manfred)


----------

