Entwickler-Ecke

Datenbanken - Hilfe bei SQL-Befehl gesucht


D. Annies - Di 30.09.08 12:34
Titel: Hilfe bei SQL-Befehl gesucht
Hi, Delpher,

mit dem folgenden SQL-Befehl kann ich die einzelnen Anzahlen ausgeben lassen.
Ich möchte aber auch gern eine Summe bilden können. Diese soll in einer showmessage-Meldung zu sehen sein.

Wer kann dabei helfen?
Mein bisheriger Befehl ist:

Delphi-Quelltext
1:
2:
3:
4:
SQL.Text := format('select distinct B.KLASSE, count(*) as ANZAHL from "%s" B ' +
                  'where B.NAME <> '''' and B.TITEL = :BAkt ' +
                  'group by B.KLASSE', [TbBuecher.tablename]);
        Parambyname('BAkt').asstring := QBuchstamm.fieldbyname('TITEL').asstring;


Vieelen Dank, Detlef


ene - Di 30.09.08 12:43

Moin,

wovon soll denn die Summe gebildet werden? Vom Prinzip sieht das so aus:


SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
SELECT DISTINCT
  B.KLASSE,
  Count(*) As Anzahl,
  Sum(Feld) As Summe,
FROM
  Tabelle As B
WHERE
  B.Name <> '' AND
  B.Titel = 'irgendwas'
GROUP BY
  B.Klasse,
  TbBuecher.Tablename


Robert.Wachtel - Di 30.09.08 13:08

@Jan: Die letzte Zeile hast Du etwas unüberlegt übernommen. :mrgreen:


ene - Di 30.09.08 13:20

Gewundert hatte ich mich schon, aber das mag am Hunger vor der Mittagspause gelegen haben ;)


D. Annies - Di 30.09.08 13:44

Hi, ene,

so schnell hatte ich keine Antwort erwartet, deshalb habe ich erst jetzt nachgesehen..

Tja, ich wollte eigentlich die einzelnen Anzahlen (!) aufsummieren, [wie] geht das??

Danke, Detlef


ene - Di 30.09.08 13:51

Soll das eine "laufende Summe" sein oder einfach die Summe aller Anzahlen? Das 2. wäre ja auch gleich die Anzahl ohne Gruppierung. Für eine laufende Summe fehlt mir grad eine Idee :(


D. Annies - Di 30.09.08 13:55

Hi, Jan,

es soll die Summe der Anzahlen sein.

Gruß, Detlef


ene - Di 30.09.08 13:58


SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
SELECT DISTINCT
  B.KLASSE,
  Count(*) As Anzahl,
  (SELECT Count(*) FROM Tabelle) As Summe,
FROM
  Tabelle As B
WHERE
  B.Name <> '' AND
  B.Titel = 'irgendwas'
GROUP BY
  B.Klasse


D. Annies - Di 30.09.08 14:27

hi, Jan,

ich komme noch nicht klar - wohl wegen der Parameter - siehe oben.

Kannst du da noch mal helfen?

Gruß, Detlef


Delete - Di 30.09.08 14:35

Willst Du nur die Summe oder die einzelnen Anzahlen zzgl. der Gesamtsumme?


ene - Di 30.09.08 14:50

Ist ein Komma zuviel


SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
SELECT DISTINCT
  B.KLASSE,
  Count(*) As Anzahl,
  (SELECT Count(*) FROM Tabelle) As Summe
FROM
  Tabelle As B
WHERE
  B.Name <> '' AND
  B.Titel = 'irgendwas'
GROUP BY
  B.Klasse


Delete - Di 30.09.08 15:04

Müsste die Where-Klausel nicht auch im Subquery auftauchen?

[edit]Anderer Vorschlag (ungetestet):

SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
SELECT 
  B.KLASSE,
  Count(1As Anzahl, 1 AS RF
FROM
  Tabelle As B
WHERE
  B.Name <> '' AND
  B.Titel = 'irgendwas'
GROUP BY
  B.Klasse
UNION
  SELECT
    'Gesamt',
    Count(1AS Anzahl, 2 AS RF
  FROM Tabelle 
  WHERE
    Name <> '' AND
    Titel = 'irgendwas'
ORDER BY RF, B.Klasse
[/edit]


Robert.Wachtel - Di 30.09.08 16:32
Titel: Re: Hilfe bei SQL-Befehl gesucht
Du möchtest die Anzahl der einzelnen Titel pro Klasse haben?

SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
SELECT
  B.KLASSE,
  B.TITEL,
  COUNT(*) AS ANZAHL
FROM
  Tabelle B
GROUP BY
  B.KLASSE,
  B.TITEL


Du möchtest die Summe der Anzahl aller Titel pro Klasse haben?

SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
SELECT
  B.KLASSE,
  COUNT(*) AS ANZAHL
FROM
  Tabelle B
GROUP BY
  B.KLASSE


Du möchtest die Summe der Anzahl aller Titel aller Klassen haben?

SQL-Anweisung
1:
2:
3:
4:
SELECT
  COUNT(*) AS ANZAHL
FROM
  Tabelle B


Oder möchtest Du was ganz anderes?


D. Annies - Di 30.09.08 17:32

Hallo,

danke erst noch mal für eure guten Ideen!

Ich gebe jetzt an, was ich bisher codiert hatte:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
leihanz := 0;
  with QBuecher2 do
  begin
    Close; SQL.Clear;
      SQL.Text := format('select count(*) as Anzahl from "%s" S ' +
                         'where S.TITEL = :p1 and S.KLASSE <> ''''', [TbBuecher.tablename]);
        Parambyname('p1').asstring := dbedit1.text;
    Open;
    leihanz := fields[0].asinteger;


Dann kam der zweite befehl, den ich schon angegeben hatte:


Delphi-Quelltext
1:
2:
3:
4:
SQL.Text := format('select distinct B.KLASSE, count(*) as ANZAHL from "%s" B ' +  
                  'where B.NAME <> '''' and B.TITEL = :BAkt ' +  
                  'group by B.KLASSE', [TbBuecher.tablename]);  
        Parambyname('BAkt').asstring := QBuchstamm.fieldbyname('TITEL').asstring;


Die Aufgabe ist also, dass ich möglichst beide Befehle in einer Anweisung habe, also lieber Robert, ich möchte die Auflistung, wer ein bestimmtes Buch hat, und wie oft das Buch insgesamt ausgeliehen ist-möglichst in einem Statement.

Vielen Dank für weitere Mühe,
Detlef


Robert.Wachtel - Di 30.09.08 17:50

user profile iconD. Annies hat folgendes geschrieben:
[...] ich möchte die Auflistung, wer ein bestimmtes Buch hat, und wie oft das Buch insgesamt ausgeliehen ist-möglichst in einem Statement. [...]

Da wäre es natürlich sehr hilfreich, wenn Du uns mal die Tabellenstruktur erläutern würdest. Aus welchen Feldern nimmst Du die Informationen?


Delete - Di 30.09.08 17:59

Hallo Detlef,

hast Du mein Statement von hier [http://www.delphi-forum.de/viewtopic.php?p=526083#526083] mal ausprobiert?

Gruß Detlef ;)


Robert.Wachtel - Di 30.09.08 18:12

user profile iconDeddyH hat folgendes geschrieben:
[...] hast Du mein Statement von hier [http://www.delphi-forum.de/viewtopic.php?p=526083#526083] mal ausprobiert? [...]

Auch da wird es schwierig zu ersehen, wer welches Buch ausgeliehen hat... :mrgreen:


Delete - Di 30.09.08 18:14

Das ist richtig, aber aus dem Ausgangsstatement auch nicht zu erkennen.


D. Annies - Di 30.09.08 19:16

Hi,

es ist wichtig, welche Klasse das Buch wie oft ausgeliehen hat, z.B.
10a hat es 25 mal und 10b hat es 23 mal. Dann möchte ich auch (nur per
showmessage) ausgeben, dass es 48 mal ausgeliehen ist. Reichen euch diese
Angaben?

Gruß, Detlef

@Deddy: deinen Befehl habe ich noch nicht probiert, weil ich mit den Zahlen nichts
anfangen kann, also mit der 1 z.B. .


Robert.Wachtel - Di 30.09.08 19:25

user profile iconD. Annies hat folgendes geschrieben:
[...] es ist wichtig, welche Klasse das Buch wie oft ausgeliehen hat, z.B.
10a hat es 25 mal und 10b hat es 23 mal. Dann möchte ich auch (nur per
showmessage) ausgeben, dass es 48 mal ausgeliehen ist. Reichen euch diese
Angaben? [...]

Nein.

Zitat:
@Deddy: deinen Befehl habe ich noch nicht probiert, weil ich mit den Zahlen nichts
anfangen kann, also mit der 1 z.B. .

Das sind Konstanten.


Delete - Di 30.09.08 19:34

Die 1 und 2 sind Konstanten für das künstliche Feld "RF" (für Reihenfolge), d.h. die Ergebnismenge soll die gruppierten Datensätze ausgeben und zum Schluss die Gesamtanzahl.


D. Annies - Di 30.09.08 20:10

Hallo Robert und Deddy,

ich denke, ich mache morgen weiter, bin irgendwie zu müde - ich melde mich wieder!!

Danke erstmal,
Detlef


D. Annies - Mi 01.10.08 09:00

Hi,

so, da bin ich wieder. Noch einmal zur Sicherheit: Ich will nicht die einzelnen Personen wissen. Beispielsweise: 10a hat das Buch 25 mal und 10b hat es 23 mal. Dann möchte ich auch (nur per showmessage) ausgeben, dass es insgesamt 48 mal ausgeliehen ist. Meine beiden Codeschnipsel habe ich auch schon angegeben, sie funktionieren auch so für sich.

Aber wie geht es in einem SQL-Befehl?

Danke, Detlef


Delete - Mi 01.10.08 09:08

Hallo Namensvetter,
ich habe ja Deine Datenstruktur nicht, aber versuch doch mal meinen SQL-Befehl von Seite 1 und schau Dir das Ergebnis an. Die künstliche Spalte "RF" musst Du dabei ja nicht im Programm anzeigen. Sollte das so nicht passen, muss man das Ganze halt nochmal überdenken. Falls doch, erklär ich es Dir gerne auch im Detail ;)


Robert.Wachtel - Mi 01.10.08 10:15

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
[...] so, da bin ich wieder. Noch einmal zur Sicherheit: Ich will nicht die einzelnen Personen wissen. Beispielsweise: 10a hat das Buch 25 mal und 10b hat es 23 mal. Dann möchte ich auch (nur per showmessage) ausgeben, dass es insgesamt 48 mal ausgeliehen ist. Meine beiden Codeschnipsel habe ich auch schon angegeben, sie funktionieren auch so für sich. [...]

Gibt es irgendeinen Grund, warum Du uns die Tabellenstruktur nicht erläutern willst?


baka0815 - Mi 01.10.08 12:35

Vielleicht solltest du die Datenstruktur ändern?

Ich würde folgende Struktur empfehlen:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
Buch
+- ID
+- Titel
+- ISBN

Klasse
+- ID
+- Jahrgang
+- Zusatz

Buch_Klasse
+- Buch_ID
+- Klasse_ID
+- Anzahl


So kannst du in der Zuordnung Buch_Klasse feststellen, wie oft das Buch in welcher Klasse vorhanden ist und bei einem Verlust/einer Neuanschaffung, etc. pp. den Wert ändern.

Wenn du nun herausfinden willst, wie oft Buch X ausgeliehen ist, machst du eine Summer über das Feld Anzahl der [code}Buch_Klasse[/code]-Tabelle anhand der Buch ID.


D. Annies - Mi 01.10.08 18:05

Hi, Robert,

tschuldige, wenn ich die Tabellenstruktur erst jetzt nachliefere:

TITEL NAME VORNAME KLASSE LEIHDAT

also, noch nicht einmal mit einer ID - aber diese Struktur musste ich leider übernehmen!

Gruß, Detlef


D. Annies - Mi 01.10.08 18:53

Hi, DeddyH,

so, nun habe ich deinen Befehl auch eingegeben, leider funktioniert er nicht.

Fehlermeldung Syntax ... beim zweiten mal Dateiname als Übergabeparameter "%s"

also, ich habe nichts gegen eine Erklärung :D zum Bleistift auch count (1) from; ich kenne bisher nur count(*) from

Gruß, DEtlef


Delete - Mi 01.10.08 19:04

OK, Teil 1:

SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
SELECT 
  B.KLASSE,
  Count(1As Anzahl, 1 AS RF
FROM
  Tabelle As B
WHERE
  B.Name <> '' AND
  B.Titel = 'irgendwas'
GROUP BY
  B.Klasse


Beim Count ist es egal, welches Feld Du nimmst, bei Verwendung einer Konstanten (in meinem Fall eben 1) ist das Ganze einen Tick performanter, da der Feldinhalt gar nicht erst ausgelesen werden muss. Die "1 AS RF" ist wie schon gesagt ein künstliches Feld für die spätere Sortierung.

Teil 2:

SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
9:
UNION
  SELECT
    'Gesamt',
    Count(1AS Anzahl, 2 AS RF
  FROM Tabelle 
  WHERE
    Name <> '' AND
    Titel = 'irgendwas'
ORDER BY RF, B.Klasse

Mit UNION kannst Du 2 Teilabfragen vereinen, solange diese die gleichen Feldtypen in der gleichen Reihenfolge zurückgeben. Das "Gesamt" ist hier wieder eine Konstante, damit das Abfrageergebnis hübsch aussieht. Das künstliche Feld RF hat nun den Wert 2, damit der Datensatz bei entsprechender Sortierung auf jeden Fall als Letzter gelistet wird.
Zum Schluss wird mit ORDER BY noch erst nach RF und dann nach Klasse sortiert. Gedachtes Abfrageergebnis ist (Beispiel):

Quelltext
1:
2:
3:
4:
5:
Klasse    Anzahl   RF
10b       10       1
3a        15       1
5d        10       1
Gesamt    35       2


Zeig doch mal, wie Du versucht hast ihn einzubauen, evtl. liegt es ja nur am "Format"-Befehl.


D. Annies - Mi 01.10.08 19:46

Hi, Deddy, genau so will ich die Ausgabe haben !!!


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
SQL.Text := format('SELECT B.KLASSE, Count(1) As Anzahl, 1 AS RF ' +
                         'FROM "%s" ' +
                         'WHERE Name <> '' AND Titel = :BAkt ' +
                         'GROUP BY Klasse ' +
                         'UNION ' +
                         'SELECT Count(1) AS Anzahl, 2 AS RF ' +
                         'FROM "%s" ' +
                         'WHERE Klasse <> '' AND Titel = :BAkt ' +
                         'ORDER BY RF, Klasse ', [TbBuecher.tablename]);
        Parambyname('BAkt').asstring := QBuchstamm.fieldbyname('TITEL').asstring;


die Fehlermeldung ist: Kein Argument für '%s'

Detlef


Robert.Wachtel - Mi 01.10.08 19:47

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:
[...] Mit UNION kannst Du 2 Teilabfragen vereinen, [...]

Vorausgesetzt, das (R)DBMS unterstützt es.


Robert.Wachtel - Mi 01.10.08 19:49

user profile iconD. Annies hat folgendes geschrieben Zum zitierten Posting springen:
[...] die Fehlermeldung ist: Kein Argument für '%s' [...]

Da Du zwei Platzhalter mit dem selben Parameter belegen willst musst Du diese natürlich qualifizieren.

Setze also anstatt %s mal %0:s.

Näheres siehe in der Online-Hilfe beim Thema Format-Strings.


Delete - Mi 01.10.08 19:50

Klar, Du hast 2 Format-Platzhalter, gibst aber nur ein Argument an.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
SQL.Text := format('SELECT B.KLASSE, Count(1) As Anzahl, 1 AS RF ' +
                         'FROM "%s" ' +
                         'WHERE Name <> '' AND Titel = :BAkt ' +
                         'GROUP BY Klasse ' +
                         'UNION ' +
                         'SELECT Count(1) AS Anzahl, 2 AS RF ' +
                         'FROM "%s" ' +
                         'WHERE Klasse <> '' AND Titel = :BAkt ' +
                         'ORDER BY RF, Klasse ', [TbBuecher.tablename,TbBuecher.tablename]);
        Parambyname('BAkt').asstring := QBuchstamm.fieldbyname('TITEL').asstring;


Robert.Wachtel - Mi 01.10.08 19:55

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:
[...]

Delphi-Quelltext
1:
2:
3:
[...]
[TbBuecher.tablename,TbBuecher.tablename]);
[...]

Das ist aber jetzt durch die Brust ins Auge, findest Du nicht? :mrgreen:


Delete - Mi 01.10.08 19:56

Aber verständlicher als die Index-Lösung ;)


D. Annies - Mi 01.10.08 20:10

Hi, ihr 2,

jetzt habe ich:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
SQL.Text := format('SELECT B.KLASSE, Count(1) As Anzahl, 1 AS RF ' +
                         'FROM "%0:s" ' +
                         'WHERE Name <> '''' AND Titel = :BAkt ' +
                         'GROUP BY Klasse ' +
                         'UNION ' +
                         'SELECT "gesamt", Count(1) AS Anzahl, 2 AS RF ' +
                         'FROM "%0:s" ' +
                         'WHERE Klasse <> '''' AND Titel = :BAkt ' +
                         'ORDER BY RF, Klasse ', [TbBuecher.tablename]);
        Parambyname('BAkt').asstring := QBuchstamm.fieldbyname('TITEL').asstring;


mit der Fehlermeldung: Ungültiger Feldname Klasse'

Wir schaffen das!
Detlef
(besser gesagt: Ihr schafft das)


Delete - Mi 01.10.08 20:15


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
SQL.Text := format('SELECT B.KLASSE, Count(1) As Anzahl, 1 AS RF ' +
                         'FROM "%s" B ' +
                         'WHERE Klasse <> '''' AND Titel = :BAkt ' +
                         'GROUP BY Klasse ' +
                         'UNION ' +
                         'SELECT "gesamt", Count(1) AS Anzahl, 2 AS RF ' +
                         'FROM "%0:s" ' +
                         'WHERE Klasse <> '''' AND Titel = :BAkt2 ' +
                         'ORDER BY RF, B.Klasse ', [TbBuecher.tablename]);
Parambyname('BAkt').asstring := QBuchstamm.fieldbyname('TITEL').asstring;
Parambyname('BAkt2').asstring := QBuchstamm.fieldbyname('TITEL').asstring;

Irgendwann klappt das schon *g*


Robert.Wachtel - Mi 01.10.08 20:25

Du immer mit Deinen unnötigen Redundanzen... :mrgreen:

Wetten, dass die Fehlermeldung bleibt? ;D


Delete - Mi 01.10.08 20:30

Wenn die oben gepostete Datenstruktur stimmt, warte ich einfach mal ab.


D. Annies - Mi 01.10.08 22:05

Hi, Kämpfer (aber lachen könnt ihr ja auch...)

wahrscheinlich geht es eleganter:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
format('SELECT KLASSE, Count(*) As Anzahl ' +
                         'FROM "%s" ' +
                         'WHERE Name <> '''' AND Titel = :BAkt ' +
                         'GROUP BY Klasse ', [TbBuecher.tablename]) +
                  format('UNION ' +
                         'SELECT "zusam", Count(*) AS Anzahl ' +
                         'FROM "%s" ' +
                         'WHERE Klasse <> '''' AND Titel = :BAkt ' +
                         'ORDER BY Klasse ', [TbBuecher.tablename]);
        Parambyname('BAkt').asstring := QBuchstamm.fieldbyname('TITEL').asstring;


aber so geht es erstmal!

Grüße aus Lübeck,
Detlef


Delete - Do 02.10.08 08:07

Eigentlich müsste das wieder den Format-Fehler von oben bringen, aber egal, wenn es jetzt funktioniert...


D. Annies - Do 02.10.08 08:56

Hi, Deddy,

so ist es manchmal, und - vielen Dank für deine Hilfe,

Detlef


Robert.Wachtel - Do 02.10.08 09:21

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:
Eigentlich müsste das wieder den Format-Fehler von oben bringen, [...]

Da jetzt zwei Format-Funktionen verwendet werden nicht.


Delete - Do 02.10.08 09:31

Das hab ich komplett übersehen :oops:


baka0815 - Do 02.10.08 09:49

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:
Beim Count ist es egal, welches Feld Du nimmst

Das möchte ich so nicht stehen lassen.

COUNT zählt in einer Spalte alle Werte, die nicht NULL sind.

Folgendes Beispiel:

Quelltext
1:
2:
3:
4:
5:
6:
TabelleA:

ID | FeldA | FeldB
 1 |     A |     B
 2 |     X |     Y
 3 |  NULL |     Z


Ein SELECT COUNT(FeldA) FROM TabelleA liefert hier 2, ein SELECT COUNT(FeldB) FROM TabelleB liefert hier 3, genau wie ein COUNT(*).


Delete - Do 02.10.08 09:53

Meinetwegen.


D. Annies - Do 02.10.08 10:25

Wieder viel gelernt, und das ist ja wohl auch der Sinn.
Detlef