Я работаю с системой закупок и выставления счетов за продукты в MS Access 2013 и пытаюсь создать SQL-запрос, который будет возвращать самую последнюю цену покупки для каждого отдельного продукта.
Вот схема таблиц, с которыми я работаю:
Мое понимание SQL очень простое, и я попробовал следующий (неправильный) запрос, в надежде, что он вернет только одну запись на элемент (из-за DISTINCT
оператора) и что он вернет только самую последнюю покупку (так как я сделал 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;
Однако приведенный выше запрос просто возвращает все покупки продуктов питания (т.е. несколько записей для каждой записи в [Food items]
), а результаты сортируются по убыванию. Может кто-нибудь объяснить мне, что я неправильно понимаю в отношении DISTINCT
оператора? То есть, почему он не возвращает только одну запись для каждого элемента в [Food items]
?
И что еще важнее - какой самый простой способ для меня - просто собрать самые последние данные о покупке продуктов питания для каждого отдельного продукта, учитывая структуру таблицы, показанную выше ? На самом деле мне важна не столько простота, сколько эффективность (база данных, с которой я работаю, довольно мала - пройдут годы, прежде чем она достигнет десятков тысяч записей). Меня больше волнует вопрос, понятный для человека, мало знакомого с SQL.
ОБНОВЛЕНИЕ: Итак, я попытался, оба из предложенных ниже ответов, и ни один из них не работает (они просто выдают синтаксические ошибки).
Основываясь на приведенных ниже предложениях и дальнейшем чтении в Интернете, я написал следующий новый запрос, используя функцию агрегирования max()
и GROUP BY
предложение:
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];
Но у меня все еще есть та же проблема: то есть, я все еще вижу более одного результата для каждого продукта. Кто-нибудь может объяснить, почему этот запрос не только возвращает самую последнюю покупку для каждого продукта питания?
ОБНОВЛЕНИЕ 2 (решено!) :
Ни один из приведенных ниже ответов не был полностью проработан, но, основываясь на некоторой серьезной модификации ответа Владимира ниже , я смог создать следующие запросы, которые, по-видимому, дают правильные результаты.
Сначала я создал это представление и назвал его «LatestInvoices»:
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
Затем я написал еще один запрос, чтобы получить необходимые поля:
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;
Спасибо всем, кто нашел время, чтобы помочь мне с этим!
[
и]
ID
столбцах, поэтому ID
в Invoices
таблице становится InvoiceID
.
DISTINCT
были отдельные столбцы. Есть ли аналогичный оператор, который будет выбирать только на основе уникальности в одном столбце? Кроме того, спасибо за советы по соглашениям об именах - да, это очень раздражает, когда приходится использовать [ ... ]
везде ... И я вижу, как включение имени таблицы в столбец ID может улучшить читаемость.
DISTINCT
возвращает строки, которые различаются по всем столбцам в строке, а не по одному столбцу.