Daten nach Kriterien in Access-Abfrage addieren
Ein Klassisches Problem beim Monatsabschluß
Hallo allerseits!
Ich versuche am Ende des Monats aus unseren Geschäftsdaten eine Abfrage zu erstellen, bei der ich direkt sehen kann, welche Kunden, welche Produkte, in welcher Menge bestellt haben.
Leider (Gott sei Dank!!) bestellen viele Kunden nicht nur einmal im Monat ein Produkt, sondern mehrfach das gleiche. Diese Produkte möchte ich jetzt direkt addiert haben.
Ein Beispiel:
Kunde A Produkt 1 Anzahl3
Kunde B Produkt 2 Anzahl2
Kunde A Produkt 1 Anzahl2
Soll werden:
Kunde A Produkt 1 Anzahl5
Kunde B Produkt 2 Anzahl2
Herzlichen Dank
Marc
Hallo allerseits!
Ich versuche am Ende des Monats aus unseren Geschäftsdaten eine Abfrage zu erstellen, bei der ich direkt sehen kann, welche Kunden, welche Produkte, in welcher Menge bestellt haben.
Leider (Gott sei Dank!!) bestellen viele Kunden nicht nur einmal im Monat ein Produkt, sondern mehrfach das gleiche. Diese Produkte möchte ich jetzt direkt addiert haben.
Ein Beispiel:
Kunde A Produkt 1 Anzahl3
Kunde B Produkt 2 Anzahl2
Kunde A Produkt 1 Anzahl2
Soll werden:
Kunde A Produkt 1 Anzahl5
Kunde B Produkt 2 Anzahl2
Herzlichen Dank
Marc
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 82007
Url: https://administrator.de/contentid/82007
Ausgedruckt am: 22.11.2024 um 18:11 Uhr
16 Kommentare
Neuester Kommentar
Grüß Dich Marc,
da müsste man mehr über die Daten/Tabellenstrukturen wissen:
Üblich hat man dann etwa 3 (hierfür relevante) Tabellen: Kunden, Bestellungen, Bestellungsdetails. Und diese stehen dann entsprechend miteinander in Beziehung.
Aber bevor man ins blaue schießt kannst Du vielleicht nochmal posten wie Ihr das in der DB implementiert habt.
BG, Felix -misterdemeanor-
da müsste man mehr über die Daten/Tabellenstrukturen wissen:
Üblich hat man dann etwa 3 (hierfür relevante) Tabellen: Kunden, Bestellungen, Bestellungsdetails. Und diese stehen dann entsprechend miteinander in Beziehung.
Aber bevor man ins blaue schießt kannst Du vielleicht nochmal posten wie Ihr das in der DB implementiert habt.
BG, Felix -misterdemeanor-
Hallo,
Das ist eigentlich schon alles, vorausgesetzt dass alle Daten in einer Tabelle stehen (was ich natürlich nicht hoffe).
SELECT <Tabellenname>.<Spalte_Kunde>, <Tabellenname>.<Spalte_Produkt>, Sum(<Tabellenname>.<Spalte_Menge>)
FROM <Tabellenname>
GROUP BY <Tabellenname>.<Spalte_Kunde>, <Tabellenname>.<Spalte_Produkt>;
Das ist eigentlich schon alles, vorausgesetzt dass alle Daten in einer Tabelle stehen (was ich natürlich nicht hoffe).
Sach ma, Bow-Bonn,
hast Du schon mal ein SQL-Statement aus der Nähe gesehen?
Ist ja nicht schlimm, wenn noch nicht.
Ich rate dringendst davon ab, eines der über den Access-Zusammenklick-Assistent automatisch generierten Skripte für "Zeig mir alles als eine meterlange Einzelsatzliste" zu nehmen und hier einfach ein GROUP BY druntersetzen zu lassen ohne dass Du die handwerklichen Kenntnisse mitbringst und ohne dass wir das Datenmodell kennen.
Kann dumm laufen und unser Statement führt dazu, dass nächsten Monat 20 eurer Kunden eine Inkasso-Mahnung bekommen oder so etwas...
Tipp: stöbere ein bisschen nach GROUP BY und Aggregatfunktionen wie SUM(), FIRST(), MAX().. und dann lass uns evtl vom Datenmodell und von einem lesbaren SQL-Statement ausgehend anfangen...
Das Dingen da ist für einen Klicki-Bunti-Generator von M$ schon ganz gut, aber hat auch noch Potentiale.
Grüße
Biber
P.S. Wenn Du Monatssummen haben willst, dann wirst Du Details wie "InvoiceDetail.Datum" wohl knicken können.
Welche Felder/Spalten willst Du?
hast Du schon mal ein SQL-Statement aus der Nähe gesehen?
Ist ja nicht schlimm, wenn noch nicht.
Ich rate dringendst davon ab, eines der über den Access-Zusammenklick-Assistent automatisch generierten Skripte für "Zeig mir alles als eine meterlange Einzelsatzliste" zu nehmen und hier einfach ein GROUP BY druntersetzen zu lassen ohne dass Du die handwerklichen Kenntnisse mitbringst und ohne dass wir das Datenmodell kennen.
Kann dumm laufen und unser Statement führt dazu, dass nächsten Monat 20 eurer Kunden eine Inkasso-Mahnung bekommen oder so etwas...
Tipp: stöbere ein bisschen nach GROUP BY und Aggregatfunktionen wie SUM(), FIRST(), MAX().. und dann lass uns evtl vom Datenmodell und von einem lesbaren SQL-Statement ausgehend anfangen...
SELECT IIf([Invoice].[Vorgangsnummer]<>"0","044") AS Entity,
Year([InvoiceDetail].[Datum]) AS [Year],
Month([InvoiceDetail].[Datum]) AS [Month],
Invoice.Artikelnummer AS ProductId,
Material.Bezeichnung1 AS ProductName,
InvoiceDetail.Kundennummer AS CustomerId,
[Customer].[Name1] & " " & [Customer].[Name2] AS CustomerName,
Invoice.Gesamtpreis AS Revenue,
Invoice.Menge AS [Qty Sold],
InvoiceDetail.Datum
FROM ((InvoiceDetail
INNER JOIN Invoice ON InvoiceDetail.Nummer = Invoice.Vorgangsnummer)
LEFT JOIN Material ON Invoice.Artikelnummer = Material.Artikel)
LEFT JOIN Customer ON InvoiceDetail.Kundennummer = Customer.Kundennummer
WHERE ((
(InvoiceDetail.Datum)>=#1/1/2008# And (InvoiceDetail.Datum)<=#12/31/2008#)
AND ((InvoiceDetail.Vorgang)="D"
Or (InvoiceDetail.Vorgang)="G"
Or (InvoiceDetail.Vorgang)="T"
Or (InvoiceDetail.Vorgang)="R")
AND ((Invoice.Positionstyp)=1))
GROUP BY InvoiceDetail.Kundennummer, Invoice.Artikelnummer;
Das Dingen da ist für einen Klicki-Bunti-Generator von M$ schon ganz gut, aber hat auch noch Potentiale.
Grüße
Biber
P.S. Wenn Du Monatssummen haben willst, dann wirst Du Details wie "InvoiceDetail.Datum" wohl knicken können.
Welche Felder/Spalten willst Du?
Der gute Mann antwortet weder Montag-Morgens, noch Samstag-Nachmittags.
Also:
Also:
- Entweder ist der Mutterkonzern Pleite gegangen weil einfach essentielle Daten gefehlt haben und keine Rechnungen mehr gestellt werden konnten-->Insolvenz
- Mutterkonzern wurde übernommen und unrelationale Stellen wurden wegrationalisiert
- Jemand ist im Urlaub und hat dreist keine Anichtskarte geschickt
- Jemand meldet sich auf einem Board an um Hilfe zu bekommen schert sich aber selbst einen Dreck um sein eigenes Problem und die Leute die Ihre Zeit investieren um zu helfen
Tja, misterdemeanor,
diese bislang 4 von Dir aufgeführten möglichen mildernden Umstände lassen mein Moderatorenherz nur für ein paar Zehntelsekunden etwas weicher werden.
Aus meiner Sicht ist ein andiskutiertes Problemchen ohne abschließende Lösung und ohne Antwort auf Nachfragen für dieses Forum so sinnvoll wie ein bildungspolitischer Sprecher der F.D.P. für die Schulpolitik.
Also verschiebe ich den Beitrag mal auf den Kompost.
Grüße und Dank für die Erinnerung
Biber
diese bislang 4 von Dir aufgeführten möglichen mildernden Umstände lassen mein Moderatorenherz nur für ein paar Zehntelsekunden etwas weicher werden.
Aus meiner Sicht ist ein andiskutiertes Problemchen ohne abschließende Lösung und ohne Antwort auf Nachfragen für dieses Forum so sinnvoll wie ein bildungspolitischer Sprecher der F.D.P. für die Schulpolitik.
Also verschiebe ich den Beitrag mal auf den Kompost.
Grüße und Dank für die Erinnerung
Biber
Na gut, Bow-Bonn,
tasten wir uns mal ran.
Wenn dieses hier Dein SQL-Schnipsel war, der zumindest die Einzelsatz-Meterware auf den Schirm gebracht hat...
...und wir mal mangels genauerer Instruktionen Deinerseits unterstellen, dass wir
die Verkaufsinformationen nach Monat/Jahr, Kunde und Artikelnummer zusammenschaufeln sollen, dann...
[diese Invoice-Vorgangsnummer tue ich mal als nicht bilanzrelevant ab..**g]
Das wäre jetzt die Variante mit den wenigsten/nur den nötigsten Anpassungen.
Die Spalte YEAR(InvoiceDetail.Datum) habe ich auskommentiert, da diese bei der WHERE-Clause eher albern aussähe.
Natürlich würde ich die JOINs in der Praxis nicht auf der unaggregierten Ebene setzen bzw. dort belassen, sondern mit dem GROUP BY-Resultset verknibbeln.
Aber um die Diskussion erst mal wieder in Schwung zu bringen....
BTW - ich verschiebe den Beitrag mal wieder zurück von Papierkorb nach Access.
Grüße
Biber
tasten wir uns mal ran.
Wenn dieses hier Dein SQL-Schnipsel war, der zumindest die Einzelsatz-Meterware auf den Schirm gebracht hat...
SELECT IIf([Invoice].[Vorgangsnummer]<>"0","044") AS Entity,
Year([InvoiceDetail].[Datum]) AS [Year],
Month([InvoiceDetail].[Datum]) AS [Month],
Invoice.Artikelnummer AS ProductId,
Material.Bezeichnung1 AS ProductName,
InvoiceDetail.Kundennummer AS CustomerId,
[Customer].[Name1] & " " & [Customer].[Name2] AS CustomerName,
Invoice.Gesamtpreis AS Revenue,
Invoice.Menge AS [Qty Sold],
InvoiceDetail.Datum
FROM ((InvoiceDetail
INNER JOIN Invoice ON InvoiceDetail.Nummer = Invoice.Vorgangsnummer)
LEFT JOIN Material ON Invoice.Artikelnummer = Material.Artikel)
LEFT JOIN Customer ON InvoiceDetail.Kundennummer = Customer.Kundennummer
WHERE ((
(InvoiceDetail.Datum)>=#1/1/2008# And (InvoiceDetail.Datum)<=#12/31/2008#)
AND ((InvoiceDetail.Vorgang)="D"
Or (InvoiceDetail.Vorgang)="G"
Or (InvoiceDetail.Vorgang)="T"
Or (InvoiceDetail.Vorgang)="R")
AND ((Invoice.Positionstyp)=1))
Order BY InvoiceDetail.Kundennummer, Invoice.Artikelnummer;
...und wir mal mangels genauerer Instruktionen Deinerseits unterstellen, dass wir
die Verkaufsinformationen nach Monat/Jahr, Kunde und Artikelnummer zusammenschaufeln sollen, dann...
[diese Invoice-Vorgangsnummer tue ich mal als nicht bilanzrelevant ab..**g]
SELECT
-- Year([InvoiceDetail].[Datum]) AS [Year],
Month([InvoiceDetail].[Datum]) AS [Month],
Invoice.Artikelnummer AS ProductId,
FIRST(Material.Bezeichnung1) AS ProductName,
InvoiceDetail.Kundennummer AS CustomerId,
FIRST([Customer].[Name1] & " " & [Customer].[Name2]) AS CustomerName,
SUM(Invoice.Gesamtpreis) AS Revenue,
SUM(Invoice.Menge) AS [Qty Sold]
FROM ((InvoiceDetail
INNER JOIN Invoice ON InvoiceDetail.Nummer = Invoice.Vorgangsnummer)
LEFT JOIN Material ON Invoice.Artikelnummer = Material.Artikel)
LEFT JOIN Customer ON InvoiceDetail.Kundennummer = Customer.Kundennummer
WHERE
(InvoiceDetail.Datum >=#1/1/2008# And InvoiceDetail.Datum<=#12/31/2008#)
AND InvoiceDetail.Vorgang IN ("D", "G", "R", "T")
AND Invoice.Positionstyp=1
GROUP BY Month([InvoiceDetail].[Datum]), InvoiceDetail.Kundennummer, Invoice.Artikelnummer;
Das wäre jetzt die Variante mit den wenigsten/nur den nötigsten Anpassungen.
Die Spalte YEAR(InvoiceDetail.Datum) habe ich auskommentiert, da diese bei der WHERE-Clause eher albern aussähe.
Natürlich würde ich die JOINs in der Praxis nicht auf der unaggregierten Ebene setzen bzw. dort belassen, sondern mit dem GROUP BY-Resultset verknibbeln.
Aber um die Diskussion erst mal wieder in Schwung zu bringen....
BTW - ich verschiebe den Beitrag mal wieder zurück von Papierkorb nach Access.
Grüße
Biber
Moin Bow,
es gibt -selbst bei dem sehr schmalbrüstigen SQL-Sprachumfang von M$-Access - keinen Grund, warum die Year()/Month()-Spalten nicht angezeigt werden sollten.
Es darf innerhalb eines Access-Statements AFAIK keine "auskommentierte" Zeile enthalten sein, d.h. die bei mir oben mit "-- " beginnende Zeile, die auskommentierte Year()-Spalte sollte raus.
Weil Kommentare was für Weicheier sind und deshalb in M$-Access nicht nötig...
Sonst poste noch mal das NICHT funktionierende Statement bitte.
Grüße
Biber
es gibt -selbst bei dem sehr schmalbrüstigen SQL-Sprachumfang von M$-Access - keinen Grund, warum die Year()/Month()-Spalten nicht angezeigt werden sollten.
Es darf innerhalb eines Access-Statements AFAIK keine "auskommentierte" Zeile enthalten sein, d.h. die bei mir oben mit "-- " beginnende Zeile, die auskommentierte Year()-Spalte sollte raus.
Weil Kommentare was für Weicheier sind und deshalb in M$-Access nicht nötig...
Sonst poste noch mal das NICHT funktionierende Statement bitte.
Grüße
Biber
Moin Bow,
sorry für die späte Rückmeldung.
Also - ein bisschen rantasten können wir uns, aber an anderen Stellen verstehe ich Dich nicht.
Fangen wir mit dem Erklärlichen an.
Wenn Du meinst, dass Erklärungen von mir leichter verständlich sind, fühle ich mich zwar geehrt, aber realistisch gesehen gibt es Sinnvolleres im Netz.
Wenn Du eine Zusammenfassungsklausel wie GROUP BY verwendest, dann stehen in der GROUP BY-Clause alle Felder, die in den betrachteten Datensätzen den gleichen Wert haben.
Alle anderen Felder müssen entweder summiert (Sum()) oder als Durchschnitt (Avg()) oder kleinste/größte/erste/letzte (Min()/Max()/First()/Last()) oder mit sonst einer Aggregatfunktion "zusammengefasst" werden.
Auf diese "IIf( ...Vorgangsnummer )" trifft nicht zu, dass sie im Group-By-Teil erwähnt wird - und es wird aber auch keine Agggatsfunktion angewendet. Genau das besagt auch die Fehlermeldung.
Also entweder dieses IIF(...) einschließen ins GROUP BY oder das Feld (dessen tieferer Sinn mir nach wie vor unklar ist) weglassen.
Unter Beachtung der obigen Regel sollte es dann funktionieren.
Unabhängig davon:
Wenn Du doch diese funktionierene Abfrage (ohne GROUP By) vorliegen hast z.B. als "Abfrage_InvoiceDetails", dann liefert diese Abfrage doch noch außen schon einen View mit den Spalten
Dann mach doch Deine draufgesattelte Abfrage einfach als
Is' doch lesbarer.
Allerdings musst Du bedenken, dass die "Abfrage_InvoiceDetails" momentan auch eine ZEIT-bezogene WHERE-Clause enthält. Diese Einschränkung würde ich rausnehmen und bei Bedarf in Deine Group-By-Abfrage setzen.
Grüße
Biber
sorry für die späte Rückmeldung.
Also - ein bisschen rantasten können wir uns, aber an anderen Stellen verstehe ich Dich nicht.
Fangen wir mit dem Erklärlichen an.
... nicht als Teil der Aggregatfunktion einschließt."
Ich hatte Dich vor einigen Postings gebeten, Dir mal ein Zeilen zum Thema GROUP BY, Aggregatfunktionen wie Sum(), First(), Last() etc durchzulesen.Wenn Du meinst, dass Erklärungen von mir leichter verständlich sind, fühle ich mich zwar geehrt, aber realistisch gesehen gibt es Sinnvolleres im Netz.
Wenn Du eine Zusammenfassungsklausel wie GROUP BY verwendest, dann stehen in der GROUP BY-Clause alle Felder, die in den betrachteten Datensätzen den gleichen Wert haben.
Alle anderen Felder müssen entweder summiert (Sum()) oder als Durchschnitt (Avg()) oder kleinste/größte/erste/letzte (Min()/Max()/First()/Last()) oder mit sonst einer Aggregatfunktion "zusammengefasst" werden.
Auf diese "IIf( ...Vorgangsnummer )" trifft nicht zu, dass sie im Group-By-Teil erwähnt wird - und es wird aber auch keine Agggatsfunktion angewendet. Genau das besagt auch die Fehlermeldung.
Also entweder dieses IIF(...) einschließen ins GROUP BY oder das Feld (dessen tieferer Sinn mir nach wie vor unklar ist) weglassen.
Unter Beachtung der obigen Regel sollte es dann funktionieren.
Unabhängig davon:
Wenn Du doch diese funktionierene Abfrage (ohne GROUP By) vorliegen hast z.B. als "Abfrage_InvoiceDetails", dann liefert diese Abfrage doch noch außen schon einen View mit den Spalten
- Entity, Year, Month, ProductId, ProductName, CustomerId, CustomerName, Revenue, [Qty Sold]
Dann mach doch Deine draufgesattelte Abfrage einfach als
SELECT Entity, Year, Month, ProductId, First(ProductName), CustomerId, First(CustomerName),
Sum(Revenue), Sum([Qty Sold]) From Abfrage_InvoiceDetails
GROUP By Entity, Year, Month, ProductId, CustomerID
ORDER By Year, Month, ProductId, CustomerID, EntityID
Is' doch lesbarer.
Allerdings musst Du bedenken, dass die "Abfrage_InvoiceDetails" momentan auch eine ZEIT-bezogene WHERE-Clause enthält. Diese Einschränkung würde ich rausnehmen und bei Bedarf in Deine Group-By-Abfrage setzen.
Grüße
Biber