SQL-Abfragen zeigen nur die neuesten Kaufdatensätze für einzelne Lebensmittel an

8

Ich arbeite mit einem Lebensmitteleinkaufs- / Rechnungssystem in MS Access 2013 und versuche, eine SQL-Abfrage zu erstellen, die den letzten Kaufpreis für jedes einzelne Lebensmittel zurückgibt.

Hier ist ein Diagramm der Tabellen, mit denen ich arbeite: Tabellen in der MS Access-Datenbank

Mein Verständnis von SQL ist sehr grundlegend, und ich habe die folgende (falsche) Abfrage versucht, in der Hoffnung, dass nur ein Datensatz pro Artikel (aufgrund des DISTINCTOperators) zurückgegeben wird und nur der letzte Kauf zurückgegeben wird (seit ich dies getan habe) ORDER BY [Invoice Date] DESC)

SELECT DISTINCT ([Food items].Item), 
    [Food items].Item, [Food purchase data].[Price per unit], [Food purchase data].[Purchase unit], Invoices.[Invoice Date]
FROM Invoices
INNER JOIN ([Food items] 
    INNER JOIN [Food purchase data] 
    ON [Food items].ID = [Food purchase data].[Food item ID]) 
ON Invoices.ID = [Food purchase data].[Invoice ID]
ORDER BY Invoices.[Invoice Date] DESC;

Die obige Abfrage gibt jedoch einfach alle Lebensmitteleinkäufe zurück (dh mehrere Datensätze für jeden Datensatz in [Food items]), wobei die Ergebnisse nach Datum sortiert sind. Kann mir jemand erklären, was ich über den DISTINCTBetreiber falsch verstehe? Das heißt, warum wird nicht nur ein Datensatz für jeden Artikel in zurückgegeben [Food items]?

Und mehr auf den Punkt gebracht - was ist für mich die einfachste Möglichkeit, die neuesten Daten zum Lebensmitteleinkauf für jedes einzelne Lebensmittel zu ermitteln, wenn man die oben gezeigte Tabellenstruktur berücksichtigt ? Effizienz ist mir weniger wichtig als Einfachheit (die Datenbank, mit der ich arbeite, ist eher klein - es wird Jahre dauern, bis sie überhaupt im Bereich von Zehntausenden von Datensätzen liegt). Es ist mir wichtiger, dass die Abfrage für jemanden mit geringen SQL-Kenntnissen verständlich ist.

UPDATE: Also habe ich versucht, beide unten vorgeschlagenen Antworten zu verwenden, und keine funktioniert (sie werfen nur Syntaxfehler auf).

Basierend auf den folgenden Vorschlägen und der Online-Lektüre habe ich die folgende neue Abfrage unter Verwendung der Aggregatfunktion max()und einer GROUP BYKlausel geschrieben:

SELECT [Food purchase data].[Food item ID], [Food purchase data].[Price per unit], max(Invoices.[Invoice Date]) AS MostRecentInvoiceDate
FROM [Food purchase data], Invoices
GROUP BY [Food purchase data].[Food item ID], [Food purchase data].[Price per unit];

Aber ich habe immer noch das gleiche Problem: Das heißt, ich sehe immer noch mehr als ein Ergebnis für jedes Lebensmittel. Kann jemand erklären, warum diese Abfrage nicht nur den letzten Kauf für jedes Lebensmittel zurückgibt?

UPDATE 2 (Gelöst!) :

Keine der folgenden Antworten hat ganz geklappt, aber aufgrund einer starken Änderung der Antwort von Vladimir konnte ich die folgenden Abfragen erstellen, die anscheinend die richtigen Ergebnisse liefern.

Zuerst habe ich diese Ansicht erstellt und sie "LatestInvoices" genannt:

SELECT InvoicesMaxDate.ItemID, InvoicesMaxDate.MaxDate, InvoicesMaxDate.MaxID
FROM [Food purchase data], Invoices, (SELECT [Food purchase data].[Food item ID] AS ItemID, MAX(Invoices.[Invoice Date]) AS MaxDate, MAX(Invoices.[Invoice ID]) AS MaxID
                FROM [Food purchase data], Invoices
                WHERE Invoices.[Invoice ID] = [Food purchase data].[Invoice ID]
                GROUP BY [Food purchase data].[Food item ID]
         )  AS InvoicesMaxDate
WHERE InvoicesMaxDate.MaxID = [Food purchase data].[Invoice ID] AND
                      InvoicesMaxDate.ItemID = [Food purchase data].[Food item ID] AND 
                      InvoicesMaxDate.MaxDate = Invoices.[Invoice Date]
GROUP BY InvoicesMaxDate.ItemID, InvoicesMaxDate.MaxDate,  InvoicesMaxDate.MaxID

Dann schrieb ich eine weitere Abfrage, um die Felder einzugeben, die ich brauchte:

SELECT [Food items].ID AS FoodItemID, [Food items].Item AS FoodItem, [Food purchase data].[Price], [Food purchase data].[Price per unit], [Food purchase data].[Purchase unit], LatestInvoices.MaxDate as InvoiceDate
FROM [Food items], [Food purchase data], LatestInvoices
WHERE LatestInvoices.[MaxID] = [Food purchase data].[Invoice ID] AND
             LatestInvoices.ItemID = [Food purchase data].[Food item ID] AND
             LatestInvoices.ItemID = [Food items].ID
ORDER BY [Food items].Item;

Vielen Dank an alle, die sich die Zeit genommen haben, mir dabei zu helfen!

J. Taylor
quelle
2
DISTINCTGibt Zeilen zurück, die für alle Spalten in der Zeile unterschiedlich sind, nicht für einzelne Spalten.
Max Vernon
2
Vermeiden Sie Leerzeichen in Ihren Tabellen- und Spaltennamen. Dann müssen Sie nicht alles mit [und]
Max Vernon
1
Und es ist (wohl) am besten, den Namen der Tabelle in alle IDSpalten aufzunehmen, damit IDin die InvoicesTabelle wird InvoiceID.
Max Vernon
Oh, das macht Sinn - ich dachte, DISTINCTdas wäre aus einzelnen Spalten. Gibt es einen analogen Operator, der nur anhand der Eindeutigkeit in einer einzelnen Spalte auswählt? Vielen Dank auch für die Tipps zu Namenskonventionen - ja, es ist sehr ärgerlich, sie [ ... ]überall verwenden zu müssen ... Und ich kann sehen, wie die Aufnahme des Tabellennamens in die ID-Spalte die Lesbarkeit verbessern würde.
J. Taylor

Antworten:

7

MS Access ist eher begrenzt.

Ich gehe davon aus, dass es möglich ist, mehr als eine Rechnung für dasselbe Datum zu haben. In diesem Fall wähle ich eine Rechnung mit der höchsten ID.

Zuerst finden wir das maximale Rechnungsdatum für jedes Lebensmittel.

SELECT
    FPD1.[Food item ID] AS ItemID
    ,MAX(I1.[Invoice Date]) AS MaxDate
FROM
    [Food purchase data] AS FPD1
    INNER JOIN Invoices AS I1 ON I1.ID = FPD1.[Invoice ID]
GROUP BY
    FPD1.[Food item ID]

Da es möglich ist, dass es mehrere Rechnungen für das gefundene maximale Datum gibt, wählen wir eine Rechnung mit der maximalen ID pro Artikel aus

Basierend auf der MS Access-Syntax verschachtelter Joins und anhand dieses Beispiels aus den Dokumenten:

SELECT fields 
FROM 
  table1 INNER JOIN 
  (
      table2 INNER JOIN 
      (
          table3 INNER JOIN tablex ON table3.field3 = tablex.fieldx
      ) ON table2.field2 = table3.field3
  ) ON table1.field1 = table2.field2
;

Versuchen wir es zusammenzusetzen:

SELECT
    InvoicesMaxDate.ItemID
    ,InvoicesMaxDate.MaxDate
    ,MAX(I2.ID) AS MaxInvoiceID
FROM
    (
        SELECT
            FPD1.[Food item ID] AS ItemID
            ,MAX(I1.[Invoice Date]) AS MaxDate
        FROM
            [Food purchase data] AS FPD1
            INNER JOIN Invoices AS I1 ON I1.ID = FPD1.[Invoice ID]
        GROUP BY
            FPD1.[Food item ID]
    ) AS InvoicesMaxDate INNER JOIN
    (
        [Food purchase data] AS FPD2 
        INNER JOIN Invoices AS I2 ON I2.ID = FPD2.[Invoice ID]
    ) ON
        InvoicesMaxDate.ItemID = FPD2.[Food item ID] AND
        --- you may need to put extra "ON" here as well, not sure
        InvoicesMaxDate.MaxDate = I2.[Invoice Date]
GROUP BY
    InvoicesMaxDate.ItemID
    ,InvoicesMaxDate.MaxDate

Jetzt haben wir sowohl die Artikel-ID als auch die ID der letzten Rechnung für diesen Artikel. Verbinden Sie dies mit Originaltabellen, um weitere Details (Spalten) abzurufen.

SELECT
    FI3.Item
    ,FI3.Item
    ,FPD3.[Price per unit]
    ,FPD3.[Purchase unit]
    ,I3.[Invoice Date]
FROM
    (
        SELECT
            InvoicesMaxDate.ItemID
            ,InvoicesMaxDate.MaxDate
            ,MAX(I2.ID) AS MaxInvoiceID
        FROM
            (
                SELECT
                    FPD1.[Food item ID] AS ItemID
                    ,MAX(I1.[Invoice Date]) AS MaxDate
                FROM
                    [Food purchase data] AS FPD1
                    INNER JOIN Invoices AS I1 ON I1.ID = FPD1.[Invoice ID]
                GROUP BY
                    FPD1.[Food item ID]
            ) AS InvoicesMaxDate INNER JOIN
            (
                [Food purchase data] AS FPD2 
                INNER JOIN Invoices AS I2 ON I2.ID = FPD2.[Invoice ID]
            ) ON
                InvoicesMaxDate.ItemID = FPD2.[Food item ID] AND
                InvoicesMaxDate.MaxDate = I2.[Invoice Date]
        GROUP BY
            InvoicesMaxDate.ItemID
            ,InvoicesMaxDate.MaxDate
    ) AS LastInvoices INNER JOIN
    (
        [Food items] AS FI3 INNER JOIN
        (
            [Food purchase data] AS FPD3
            INNER JOIN Invoices AS I3 ON I3.ID = FPD3.[Invoice ID]
        ) ON FI3.ID = FDP3.[Food item ID]
    ) ON
        LastInvoices.MaxInvoiceID = I3.ID AND
        LastInvoices.ItemID = FI3.ID

In der Praxis würde ich eine Ansicht für die erste Abfrage mit einem einzelnen Join erstellen. Dann würde ich eine zweite Ansicht erstellen, die die erste Ansicht mit den Tabellen verbindet, dann die dritte Ansicht usw., um die verschachtelten Verknüpfungen zu vermeiden oder sie zu minimieren. Die Gesamtabfrage wäre leichter zu lesen.


Bearbeiten Sie , um zu klären, was ich meine, basierend auf Ihrer endgültigen Lösung, die Sie in die Frage gestellt haben.

Ein letzter Versuch, meine Botschaft zu übermitteln.

Dies ist, was Sie basierend auf meinen obigen Vorschlägen geschrieben haben:

SELECT
    InvoicesMaxDate.ItemID
    ,InvoicesMaxDate.MaxDate
    ,Invoices.[Invoice ID]
FROM [Food purchase data], Invoices, 
    (
        SELECT 
            [Food purchase data].[Food item ID] AS ItemID
            ,MAX(Invoices.[Invoice Date]) AS MaxDate
        FROM [Food purchase data], Invoices
        WHERE Invoices.[Invoice ID] = [Food purchase data].[Invoice ID]
        GROUP BY [Food purchase data].[Food item ID]
    )  AS InvoicesMaxDate
WHERE
    Invoices.[Invoice ID] = [Food purchase data].[Invoice ID] AND
    InvoicesMaxDate.ItemID = [Food purchase data].[Food item ID] AND 
    InvoicesMaxDate.MaxDate = Invoices.[Invoice Date]
GROUP BY InvoicesMaxDate.ItemID, InvoicesMaxDate.MaxDate, Invoices.[Invoice ID];

Das habe ich gemeint:

SELECT
    InvoicesMaxDate.ItemID
    ,InvoicesMaxDate.MaxDate
    ,MAX(Invoices.[Invoice ID]) AS [Invoice ID]
FROM [Food purchase data], Invoices, 
    (
        SELECT
            [Food purchase data].[Food item ID] AS ItemID
            ,MAX(Invoices.[Invoice Date]) AS MaxDate
        FROM [Food purchase data], Invoices
        WHERE Invoices.[Invoice ID] = [Food purchase data].[Invoice ID]
        GROUP BY [Food purchase data].[Food item ID]
    )  AS InvoicesMaxDate
WHERE
    Invoices.[Invoice ID] = [Food purchase data].[Invoice ID] AND
    InvoicesMaxDate.ItemID = [Food purchase data].[Food item ID] AND 
    InvoicesMaxDate.MaxDate = Invoices.[Invoice Date]
GROUP BY InvoicesMaxDate.ItemID, InvoicesMaxDate.MaxDate;

Sehen Sie den Unterschied?

Die InvoicesMaxDategibt MAX Invoice Datefür jeden zurück Food item ID. Wenn es zwei Rechnungen für dieselbe Food item IDmit derselben MAX gibt Invoice Date, sollten wir eine Rechnung unter ihnen auswählen. Dies erfolgt durch Gruppieren nach InvoicesMaxDate.ItemID, InvoicesMaxDate.MaxDate. Hier sollte es keine Gruppierung geben Invoices.[Invoice ID], da wir die Rechnung mit der maximalen ID auswählen möchten.

Sobald Sie diese Abfrage als LatestInvoicesAnsicht gespeichert haben , wird sie weiter verwendet, wie Sie sie richtig geschrieben haben (beachten Sie, dass die endgültige Abfrage LatestInvoices.[Invoice ID]und verwendet LatestInvoices.ItemID, aber nicht verwendet LatestInvoices.MaxDate):

SELECT 
    [Food items].ID as FoodItemID
    ,[Food items].Item as FoodItem
    ,[Food purchase data].[Price]
    ,[Food purchase data].[Price per unit]
    ,[Food purchase data].[Purchase unit]
    ,Invoices.[Invoice Date]
FROM [Food items], [Food purchase data], Invoices, LatestInvoices
WHERE 
    Invoices.[Invoice ID] = [Food purchase data].[Invoice ID] AND
    [Food items].ID = [Food purchase data].[Food item ID] AND
    LatestInvoices.[Invoice ID] = Invoices.[Invoice ID] AND 
    LatestInvoices.ItemID = [Food items].ID
ORDER BY [Food items].Item

Warum gibt Ihre letzte Abfrage in der Frage mehrere Zeilen pro Element zurück:

SELECT 
    [Food purchase data].[Food item ID]
    , [Food purchase data].[Price per unit]
    , max(Invoices.[Invoice Date]) AS MostRecentInvoiceDate
FROM [Food purchase data], Invoices
GROUP BY [Food purchase data].[Food item ID], [Food purchase data].[Price per unit];

Sie gruppieren hier nach [Food item ID]und [Price per unit], sodass Sie so viele Zeilen erhalten, wie es eindeutige Kombinationen dieser beiden Spalten gibt.

Die folgende Abfrage würde eine Zeile pro zurückgeben [Food item ID].

SELECT 
    [Food purchase data].[Food item ID]
    , max(Invoices.[Invoice Date]) AS MostRecentInvoiceDate
FROM [Food purchase data], Invoices
GROUP BY [Food purchase data].[Food item ID];

Eine Randnotiz, die Sie wirklich explizit INNER JOINanstelle von verwenden sollten ,. Diese Syntax ist 20 Jahre alt.

SELECT 
    [Food purchase data].[Food item ID]
    , max(Invoices.[Invoice Date]) AS MostRecentInvoiceDate
FROM
    [Food purchase data]
    INNER JOIN Invoices ON Invoices.ID = [Food purchase data].[Invoice ID]
GROUP BY [Food purchase data].[Food item ID];
Vladimir Baranov
quelle
Vielen Dank für Ihre sehr ausführliche Antwort! Die erste Abfrage, die Sie geteilt haben, hat funktioniert und tatsächlich das letzte Rechnungsdatum für jedes einzelne Lebensmittel abgerufen, was sehr hilfreich ist. Als ich jedoch die nächsten 2 von Ihnen geteilten Abfragen ausprobierte, bekam ich "Syntax error (missing operator) in query expression"den Ausdruck INNER JOIN Invoices AS I2 ON I2.ID = FPD2.[Invoice ID]... Ich werde mehr damit herumspielen, um zu sehen, ob ich es zum Laufen bringen kann.
J. Taylor
@JesseTaylor, offenbar ist es notwendig , explizit setzen Klammern (und )wenn Abfrage mehrere verwendet schließt sich und die bewegen ONKlausel ein wenig herum. Ich habe keinen Zugriff zum Überprüfen, aber ich kann versuchen, die richtige Syntax zu erraten, indem ich die Dokumente später heute lese.
Vladimir Baranov
@ JesseTaylor, ich habe die Antwort aktualisiert und hoffe, dass ich die Syntax richtig errate. Bitte versuchen Sie es und lassen Sie mich wissen, ob es funktioniert.
Vladimir Baranov
1
@ JesseTaylor, du bist willkommen. Es ist schon eine Weile her, dass ich Access verwendet habe und es ist schwierig, die Syntax richtig zu machen. Ein Hinweis zu Ihrer Ansicht LatestInvoices: Das Finale GROUPsollte BY InvoicesMaxDate.ItemID, InvoicesMaxDate.MaxDatenur ohne sein Invoices.[Invoice ID]. In dem SELECTTeil sollte es sein MAX(Invoices.[Invoice ID]) AS [Invoice ID]. Das ist der springende Punkt. Zuerst (in der inneren Abfrage) finden wir GROUP BY [Food item ID]das maximale Rechnungsdatum. Es kann mehrere Rechnungen mit diesem Datum geben, daher gibt es eine Sekunde Zeit GROUP BY, um eine Rechnung mit maximaler ID auszuwählen.
Vladimir Baranov
1
@ JesseTaylor, leider hast du mich falsch verstanden. Ich habe meine Antwort aktualisiert, um Ihnen zu zeigen, was ich meinte. Um den Unterschied zu erkennen, fügen Sie Ihren (Beispiel-) Daten zwei Rechnungen für dasselbe ItemIDmit demselben großen Datum hinzu und versuchen Sie beide Abfragen.
Vladimir Baranov
3

Eine Abfrage, die sofort funktioniert:

SELECT Fi.Item, Fpd.[Price per unit], Fpd.[Purchase unit]
FROM [Food items] Fi INNER JOIN [Food purchase data] Fpd
ON Fpd.[Food item ID] = Fi.ID
WHERE Fpd.[Invoice ID] = (
  SELECT TOP 1 I.ID 
  FROM Invoices I INNER JOIN [Food purchase data] Fpd2
  ON Fpd2.[Invoice ID] = I.ID
  WHERE Fpd2.[Food item ID] = Fpd.[Food item ID]
  ORDER BY I.[Invoice Date] DESC
)
aksenoff
quelle
Wenn ich diese Abfrage ausführe, wird nur die Fehlermeldung angezeigt: "Von dieser Unterabfrage kann höchstens ein Datensatz zurückgegeben werden." Die Datenblattansicht zeigt nur einen Datensatz mit "#NAME?" in jedem Bereich.
J. Taylor
3

Ich könnte es mit der folgenden Abfrage lösen:

Select MAX(AllItemBuyings.[invoice date]) as RecentBuyingDate, AllItemBuyings.[Food Item Id]  From 
(    
    select fpd.[Invoice Id], fpd.[Food Item Id], I.[invoice date] From [Food purchase data]as fpd 
    inner join invoices I on fpd.[Invoice Id] = I.ID

) as AllItemBuyings    
Group By AllItemBuyings.[Food Item Id]

Da ich keinen Zugriff habe, habe ich dies auf SQL Server getestet. Ich hoffe das wird für dich funktionieren.

Bearbeiten / Zusätzliche Abfrage : Um die anderen Spalten der Lebensmittelelementtabelle hinzuzufügen, habe ich die Abfrage geändert. Ich habe es auf eine Weise gemacht, die ich nicht wirklich mag. Ob es für Sie in Ordnung ist, hängt von Ihren Daten und Anforderungen ab. Ich habe mich mit dem Bestelldatum wieder der Tabelle INVOICES angeschlossen. Falls dies ein Datum ist, einschließlich der Zeit, zu der ich trainiere, beachten Sie dies bitte. Ich sehe keinen anderen Weg in Ihrem Szenario. Vielleicht gibt es eine bessere Lösung mit rekursiven Abfragen ...?

Bitte probieren Sie es aus und lassen Sie mich wissen, ob es funktioniert:

Select Recents.RecentBuyingDate, pd.* From 
(

   Select MAX(AllItemBuyings.[invoice date]) as RecentBuyingDate, AllItemBuyings.[Food Item Id]    From 
    (    
        select fpd.[Invoice Id], fpd.[Food Item Id], I.[invoice date], fpd.ID From [Food purchase data]as fpd 
        inner join invoices I on fpd.[Invoice Id] = I.ID

    ) as AllItemBuyings    
    Group By AllItemBuyings.[Food Item Id]

    ) as Recents    
    Join Invoices i on i.[invoice date] = Recents.RecentBuyingDate
    Join [Food purchase data] pd ON pd.[Invoice Id] = i.ID AND pd.[Food Item Id] = Recents.[Food Item Id]
Magier
quelle
Vielen Dank. Dies gibt mir korrekt das letzte Kaufdatum für jeden Artikel. Wie würde ich diese, obwohl zu ziehen , in allen Feldern , dass ich in der Frage erwähnt (zB Item, Price per unitusw.)?
J. Taylor
Die neue Abfrage, die Sie vorgeschlagen haben, löst nur eine Fehlermeldung aus, die nichts anderes als "Syntaxfehler in FROM-Klausel" sagt.
J. Taylor
Möglicherweise erfordert Access, dass die JOIN-Operation genau "INNER JOIN" ist. Versuchen Sie INNSER JOIN anstatt nur JOIN.
Magier
2

Ich glaube, das Folgende sollte funktionieren.

SELECT fi.[Item], fd.[Price per unit], MAX(i.[Invoice Date])
FROM [Invoices] AS i
INNER JOIN [Food Purchase Data] AS fd
    ON i.ID = fd.[Invoice ID]
INNER JOIN [Food items] AS fi
    ON fd.[Food item ID] = fi.ID
GROUP BY fi.Item, fd.[Price per unit]
ORDER BY i.[Invoice Date] DESC

Warum Ihre Abfrage nicht die gewünschten Ergebnisse zurückgibt:

SELECT [Food purchase data].[Food item ID], [Food purchase data].[Price per unit], max(Invoices.[Invoice Date]) AS MostRecentInvoiceDate
FROM [Food purchase data], Invoices
GROUP BY [Food purchase data].[Food item ID], [Food purchase data].[Price per unit];

Das größte Problem, das ich sehe, ist, dass Sie nicht wirklich etwas tun, um sich Ihren Tischen anzuschließen. Der implizite "Join", der durch einfaches Auflisten beider in Ihrer FROM-Klausel vorhanden ist, gibt Ihnen ein kartesisches Produkt. Grundsätzlich wird jede mögliche Kombination in Ihrer Datenbank für die Felder zurückgegeben, die Sie abfragen.

Wenn die beiden Tabellen beispielsweise jeweils 3 Datensätze enthalten, anstatt das letzte Datum zurückzugeben, würde Ihre Abfrage etwa Folgendes zurückgeben: 1,1 1,2 1,3 2,1 2,2 2,3 3,1 3,2 3 ,3

Es ist sehr wichtig, dass Sie Ihre Joins explizit deklarieren. Sie können dies in Ihrer Abfrage auf zwei Arten tun:

FROM [Food purchase data] AS fd, [Invoices] AS i
WHERE fd.[Invoice ID] = i.[ID]

ODER

FROM [Food purchase data] AS fd
INNER JOIN [Invoices] AS i
    ON fd.[Invoice ID] = i.[ID]

Aktualisierte Abfragen: Wenn diese immer noch nicht funktionieren, entfernen Sie die Aliase und verwenden Sie die vollständig qualifizierten Spaltennamen.

agpoweredmg
quelle
Lassen Sie uns diese Diskussion im Chat fortsetzen .
Agpoweredmg
0

Ich stimme den Vorschlägen von Max zu Ihrem Datenmodell zu. Durch die Implementierung dieser wird Ihr SQL auf lange Sicht besser lesbar.

Vor diesem Hintergrund zeigt DISTINCT eindeutige Zeilen an. Um nur die aktuellsten anzuzeigen, müssen Sie die angezeigten Spalten einschränken.

Versuchen Sie etwas wie:

SELECT [Food purchase data].[Food item ID], max(Invoices.[Invoice Date]) AS MostRecentInvoiceDate
FROM Invoices 
INNER JOIN ([Food items] ON [Food items].ID = [Food purchase data].[Food item ID]) 
GROUP BY [Food purchase data].[Food item ID]

(Übersetzung: Zeigen Sie für jeden Artikel im Geschäft das letzte Rechnungsdatum an.)

Sie können dies als Ansicht speichern und in einer anderen Abfrage wie in einer Tabelle verwenden. Sie können also einen inneren Join auf der Rechnung für den Kaufpreis durchführen und sich auf den anderen Tabellen verbinden, wenn Sie diese Details benötigen.

(Theoretisch könnten Sie auch eine verschachtelte Abfrage durchführen, aber da Sie einfach angefordert haben, ist eine gespeicherte Abfrage einfacher.)

UPDATE basierend auf Ihrem Update:

Ich werde WHERE-Klauseln anstelle von JOINS verwenden, da ich MS Access nicht zur Hand habe. Sie sollten in der Lage sein, die GUI zu verwenden, um die Verbindungen zwischen den Tabellen in MS Access basierend auf diesen Informationen herzustellen. (Bitte geben Sie eine SQLFiddle an, wenn Sie wirklich Hilfe bei der weiteren Fehlerbehebung benötigen.)

Schritt 1: Speichern Sie dies als ANSICHT (z. B. "MostRecentInvoice")

SELECT [Food purchase data].[Food item ID] AS FoodItemID, max(Invoices.[Invoice Date]) AS MostRecentInvoiceDate
FROM [Food purchase data], Invoices
WHERE [Food purchase data].[Food item ID] = Invoices.ID
GROUP BY [Food purchase data].[Food item ID];

Schritt 2: Verwenden Sie die Ansicht in einer zweiten Abfrage

SELECT (list all the fields you need here)
FROM MostRecentInvoice, Invoices, etc...
WHERE MostRecentInvoice.FoodItemID = [Food purchase data].[Food item ID] 
AND MostRecentInvoice.MostRecentInvoiceDate = Invoices.[Invoice Date]
AND (whatever else joins you'll need for the other tables)

... und um Ihre Frage zu beantworten: Die zweite Abfrage im Update funktioniert nicht, da sich die Spalte [Preis pro Einheit] in Ihren Anweisungen SELECT und GROUP BY befindet. Dies bedeutet im Wesentlichen, dass Sie ALLE möglichen Werte von [Preis pro Einheit] anzeigen möchten, obwohl Sie wirklich nur einen Wert wünschen: den neuesten Wert.

Chabzjo
quelle
Vielen Dank, aber wenn ich versuche, die von Ihnen freigegebene Abfrage auszuführen, wird nur eine Fehlermeldung angezeigt: "Syntaxfehler bei JOIN-Operation."
J. Taylor
Leider hatte ich keine Zeit, die Tabellen in Access selbst zu erstellen. Ich nahm an, dass Sie einige Erfahrungen mit Joins gemacht haben, da einige in Ihrer Frage waren. Haben Sie versucht, es mit Create -> Query in Access zu erstellen?
Chabzjo
Die erste Abfrage, die Sie geteilt haben, liefert aufgrund der Zeile keine korrekten Ergebnisse WHERE [Food purchase data].[Food item ID] = Invoices.ID... Ich nehme an, Sie haben gemeint, WHERE [Food purchase data].[Invoice ID] = Invoices.[Invoice ID]aber das gibt immer noch mehrere Daten pro Lebensmittel zurück, anstatt nur die aktuellsten.
J. Taylor