# SQL Abfrage Bestellung



## 0plan (8. Jun 2012)

Hallo,

ich beschäftige mich momentan mit SQL bin da leider noch nicht so fit. Meine Frage bezieht sich auf folgende Anweisung


```
SELECT bk_bestellung_id, bk_lieferantenname, bk_status, bk_lieferdatum, bk_auftragsnummer, BZ_GEWICHT
       FROM BESTELLKOPF, BESTELLZEILEN
             WHERE bk_bestellung_id = bz_bestellung_id
                  AND upper(BK_LIEFERANTENNAME) LIKE upper('%' || :Lieferant || '%')
                  AND BK_LIEFERDATUM between to_date('01.01.2012') AND to_date('31.12.2012')
                  AND bk_status <>'STORNIERT'
                  order by BK_LIEFERDATUM
```

Diese ABfrage erstellt mir die benötigte Tabelle mit den Werten die ich brauche, in dieser Ergebnistabelle befindet sich dann auch die Spalte BZ_GEWICHT.  

Ich muss diese BZ_Gewicht Spalte nun aber addieren, da es darum eigentlich auch geht. Wie bekomme ich denn auf die Ergebnistabelle am Schluss die sum() Funktion auf eine Spalte der Tabelle?


----------



## Evil-Devil (8. Jun 2012)

Die Gewichtssumme bezieht sich auf eine Lieferung oder?
In dem Fall gruppierst du einfach nach bk_bestellung_id.

[sql]
SELECT	bk_bestellung_id, bk_lieferantenname, bk_status,
		bk_lieferdatum, bk_auftragsnummer, BZ_GEWICHT,
		SUM(BZ_GEWICHT) as lieferungsgewicht
FROM	BESTELLKOPF, BESTELLZEILEN
WHERE	bk_bestellung_id = bz_bestellung_id
AND	upper(BK_LIEFERANTENNAME) LIKE upper('%' || :Lieferant || '%')
AND	BK_LIEFERDATUM BETWEEN to_date('01.01.2012') AND to_date('31.12.2012')
AND	bk_status <>'STORNIERT'
GROUP BY	bk_bestellung_id
ORDER BY	BK_LIEFERDATUM
[/sql]

Das sollte dir das gewünschte Ergebnis zurückliefern, wenn ich dich richtig verstanden habe.


----------



## 0plan (8. Jun 2012)

Das hast du richtig erkannt, jedoch bekomme ich eine Fehlermeldug 

ORA - Kein Group By Ausdruck

wenn ich die Abfrage ausführe


----------



## Evil-Devil (8. Jun 2012)

Welche SQL Software nutzt?


----------



## 0plan (8. Jun 2012)

Eine von einem Kollegen in Delphi geschriebene Software für Oracle Datenbanken, ziemlich mächtiges Teil.


----------



## Evil-Devil (8. Jun 2012)

Ok, dann frag am besten den Kollegen wieso das Group By dort nicht funktioniert, weil wenn ich über Google mir das Group By zu Oracle SQL anschaue erkenne ich keinen Unterschied.

Alternativ den SQL Befehl direkt auf dem Datenbank Server mal ausprobieren


----------



## SlaterB (8. Jun 2012)

meines Wissens nach muss man nach der ganzen Reihe an abgefragen Attributen, nach 
> bk_bestellung_id, bk_lieferantenname, bk_status,  bk_lieferdatum, bk_auftragsnummer, BZ_GEWICHT
auch gruppieren,

das dürfte SQL-Standard sein, oder wirklich anders kennengelernt?
dass bk_bestellung_id vielleicht Primärschlüssel ist, und damit auch andere eindeutig werden läßt,
ist wohl bisschen zu viel an Intelligenz für eine Query erwartet, die geht eher technischer vor

alternative Abkürzung geht irgendwie Richtung
SELECT DISTINCT a, b, c, usw.

---

edit:
wenn BZ_GEWICHT summiert wird, dann danach natürlich NICHT selektieren + gruppieren


----------



## 0plan (8. Jun 2012)

Slater hat recht, ich habe natürlich vergessen die Felder zu gruppieren. Es funktioniert jetzt alles. Leider sind die Fehlermeldung bei dem selbst programmierten Programm nicht so ausführlich was mich teilweise verwirrt. Das ist auch meine erste Abfrage wofür ich Group By verwenden musste, daher mein weniger fundiertes Fachwissen diesbezüglich. Danke an alle


----------



## Evil-Devil (8. Jun 2012)

Gruppieren und selektieren geht natürlich in SQL. Alles andere wäre ja sinnlos, wenn man Aggregat Funktionen nur alleine ausführen kann.

@mehr gruppieren: Das kommt ganz darauf an nach was man die Zeilen aufgesplittet haben will.
Wenn er zb. noch wissen will wv. die die Inhalte des jeweiligen Herstellers wiegen würden, könnte er zusätzlich zur Lieferungs ID noch nach der Hersteller ID gruppieren. Die Möglichkeiten sind nahzu endlos 

[edit]
Erwartet Oracle tatsächlich das man alle Felder noch einmal angibt? Das ist afaik kein SQL Standard und wenn dann ein sehr alter.
[/edit]


----------



## 0plan (8. Jun 2012)

> Erwartet Oracle tatsächlich das man alle Felder noch einmal angibt? Das ist afaik kein SQL Standard und wenn dann ein sehr alter.


Das hat mich auch verwirrt, find ich ziemlich nervig

Ergebnis sieht nun so aus :


```
SELECT BK_LIEFERANTENNAME as LIEFERANT,
       BZ_WERKSTOFF,
       BZ_ARTIKELGRUPPE,
       BZ_AD_1,
       BZ_WS_1,
       BZ_MENGE,
       BZ_EINGANG,
       BZ_LIEFERJAHR as LIEFERJAHR,
       SUM(BZ_GESAMTGEWICHT) as GESAMT_GEWICHT

       FROM BESTELLKOPF, BESTELLZEILEN
             WHERE bk_bestellung_id = bz_bestellung_id
                  AND upper(BK_LIEFERANTENNAME) LIKE upper('%' || :Lieferant || '%')
                  AND BZ_LIEFERJAHR ='2012'
                  AND bk_status <>'STORNIERT'
                  AND bk_status <>'GESTOPPT'
                  GROUP BY BK_LIEFERANTENNAME, BZ_LIEFERJAHR, BZ_MENGE, BZ_WERKSTOFF, BZ_ARTIKELGRUPPE, BZ_EINGANG, BZ_AD_1, BZ_WS_1
                  ORDER BY LIEFERANT
```


----------



## SlaterB (8. Jun 2012)

Evil-Devil hat gesagt.:


> Erwartet Oracle tatsächlich das man alle Felder noch einmal angibt? Das ist afaik kein SQL Standard und wenn dann ein sehr alter.


was wäre die Alternative, wie erklärst du diese?
soll man gar kein Group By schreiben?
du hast ja selber eins eingefügt mit einem Attribut, wieso gerade dieses und warum sollte es reichen?
wie ich schon fragte weil (hoffentlich) Primärschlüssel?

wenn das nicht wäre und man nach 4 beliebig kombiniert verteilten Kategorien gruppieren möchte,
wären dann zumindest alle 4 aufzuführen? 

bei Joins, vielleicht Attributen von mehreren Tabellen, etwa hier auch was von BESTELLZEILEN, 
hätte man ja ganz schön nachzudenken, was reicht und was doch einzeln genannt werden muss..


----------



## Evil-Devil (8. Jun 2012)

SlaterB hat gesagt.:


> wenn das nicht wäre und man nach 4 beliebig kombiniert verteilten Kategorien gruppieren möchte,
> wären dann zumindest alle 4 aufzuführen?


Ja wären sie.

Nach jeder Spalte die man aggregiert haben will gruppiert man. Im Beispiel brauchten wir nur eine Spalte.

In seinem Beispiel waren es die Gesamtgewichte pro Lieferung. Wenn er zusätzlich noch nach Gewicht gruppiert hätte, hätte er neben den Liefergewicht auch das Einzelgewicht jedes Artikels erhalten.


Allerdings kann man mit Group By auch einige witzige/nützliche Dinge machen.
Zb. Altersbereiche gruppieren.

[sql]
select count(*) as anzahl, min(age) as min_age, max(age) as max_age
from teilnehmer_menge
group by age between 18 and 30, age between 31 and 45, age between 46 and 65
[/sql]

Im Select könnte man noch IF/SWITCH einbauen für genauere Bezeichner, nur ist das bei solch speziellen Abfragen meist überflüssig.


----------



## SlaterB (8. Jun 2012)

> Nach jeder Spalte die man aggregiert haben will gruppiert man. Im Beispiel brauchten wir nur eine Spalte. [..] waren es die Gesamtgewichte

was haben die Gewichte mit der Gruppierung zu tun? die Gewichte sind das EINZIGE, nach dem NICHT gruppiert wird  ,
dort nur die Summe und fertig,

die Summe über die ganze Tabelle wäre ganz ohne Gruppierung zu schaffen,
aber die will man ja nicht, sondern nach 1-n Attributen

nochmal mit Beispielen angefangen:
[sql]
select a, summe(gewicht) from x
group by a
[/sql]
wirst du sicherlich zustimmen

nun aber
[sql]
select a, b summe(gewicht) from x
group by a, b
[/sql]
warum hier nicht sowohl nach a und b gruppieren? was spricht dagegen, was wäre die Alternative?
(außer DISTINCT-Schreibweise vielleicht)


----------



## Evil-Devil (8. Jun 2012)

In deinem Beispiel verwendest du nur eine Tabelle. Wir haben oben zwei Tabellen.

Warum soll denn nach a und b gruppiert werden? Du gruppierst doch nur auf das was du gruppieren willst.
Wie eben oben das Gewicht pro Lieferung und das Einzelgewicht entstammt den Positionen.

Wenn ich jetzt also das Gesamtgewicht der Lieferung und die Einzelgewichte haben will kann ich nach a und b gruppieren. Will ich aber nur das Gesamtgewicht haben gruppiere ich nur nach a.

Irgendwie drehen wir uns im Kreis ^^"

[sql]
select a.lieferungs_id, sum(b.gewicht) gesamt
from lieferung a, positionen b
where a.lieferungs_id = b.lieferungs_id
group by a.lieferungs_id
[/sql]

1 / 220
2 / 120
3 / 600


[sql]
select a.lieferungs_id, b.gewicht, sum(b.gewicht) gesamt
from lieferung a, positionen b
where a.lieferungs_id = b.lieferungs_id
group by a.lieferungs_id, b.positions_id
[/sql]

1 / 60 / 220
1 / 70 / 220
1 / 90 / 220
2 / 40 / 120
2 / 40/  120
2 / 40 / 120
3 / 200 / 600
3 / 100 / 600
3 / 300/  600


----------



## SlaterB (8. Jun 2012)

schau dir die Struktur der Query um die es hier geht, an,
es wird ein Gewicht summiert, mehr ist dazu nicht zu sagen, auch wenn es anscheinend mehrere Spalten gibt,
für die Query ist nur wichtig dass da sum(spalte) steht, als zu Einzelgewicht usw. bitte nicht mehr abzweigen,
es wird ein Gewicht summiert,

was die Summe bedeutet, pro Lieferung, pro Jahr usw., das hängt von den restlichen Attributen der Query ab,
und meine Aussage ist:
da stehen noch 5 weitere, "bk_bestellung_id, bk_lieferantenname, bk_status, bk_lieferdatum, bk_auftragsnummer",

dass das inhaltlich 'pro Lieferung, Rest Beiwerk' bedeutet, kann man meiner Ansicht nach von der Query nicht als Interpretation zumuten,
es sind ganz einfach 5 beliebige Attribute, und daher muss nach allen 5 gruppiert werden, Ausnahmen gibts nicht, alle sind gleich

naja, spannend ist das auch nicht weiter, bei mir bei Oracle geht es eh nur so, das sehe ich ja selber


----------



## Evil-Devil (8. Jun 2012)

SlaterB hat gesagt.:


> dass das inhaltlich 'pro Lieferung, Rest Beiwerk' bedeutet, kann man meiner Ansicht nach von der Query nicht als Interpretation zumuten,
> es sind ganz einfach 5 beliebige Attribute, und daher muss nach allen 5 gruppiert werden, Ausnahmen gibts nicht, alle sind gleich



Naja, wie ich gerade aufm Wikipedia Artikel lesen durfte lassen tatsächlich einige Hersteller diese Optimierung weg - sprich man muss wie von euch aufgezeigt alles angeben. SQL sieht dies normalerweise nicht vor. Und von MySQL und MS SQL kenne ich es auch nicht anders.

Ich stell mir das jedenfalls sehr nervig vor, wenn ich einen Query mit vielen Spalten und Funktionen hätte. Den müsste ich ja erst in kleinere aufdröseln im schlechtesten Fall.


----------

