问题
I am trying to produce a database to manage maintenance of equipment. I have two tables:
- One (Inventory) containing details of each piece of equipment, including Purchase Date and Service Period,
- One containing details of work done (WorkDone), including the date the work was carried out (Work Date).
I would like a query that displays the date that it should be next serviced. So far I have:
SELECT Max(DateAdd('m', [Inventory].[Service Period],
[WorkDone].[Work Date])) AS NextServiceDate,
Inventory.Equipement
FROM Inventory INNER JOIN WorkDone ON Inventory.ID = WorkDone.Equipment
GROUP BY Inventory.Equipement
This works well as long as some work done has been registered for a given piece of equipment. If no work has been carried out I would like the NextServiceDate to also show
DateAdd('m',[Inventory].[Service Period], [Inventory].[Purchase Date])
However, I cannot work out how to get SQL/MS access to compare two values and only display the greater of the two. From reading around I think I should be able to do a sub-query, but I cannot work out how to phase it.
I've been trying to adapt @MikeTeeVee's answer from here: Is there a Max function in SQL Server that takes two values like Math.Max in .NET?. But I keep getting errors saying that query is not part of an aggregate function and I'm not certain what I doing wrong. For example, I tried:
SELECT Inventory.Equipement,
(SELECT MAX(NSD_proxy)
FROM (VALUES
(Max(DateAdd('m', Inventory.[Service Period], WorkDone.[Work Date]))),
(DateAdd('m', Inventory.[Service Period], Inventory.[Purchase Date])))
AS FUNCTION(NSD_proxy)
) AS NextServiceDate,
FROM Inventory INNER JOIN WorkDone ON Inventory.ID = WorkDone.Equipment
GROUP BY Inventory.Equipement
which has some syntax error.
回答1:
Consider a LEFT JOIN
to return matched or unmatched records where latter is filled with NULLs, and then run your aggregate, MAX
, with an NZ():
SELECT Max(NZ(DateAdd('m', i.[Service Period], w.[Work Date]),
DateAdd('m', i.[Service Period], i.[Purchase Date]))
) AS NextServiceDate, i.Equipement
FROM Inventory i LEFT JOIN WorkDone w ON i.ID = w.Equipment
GROUP BY i.Equipement
回答2:
You don't have to compare the two dates, just check if a WorkDone
record exists to match the Inventory
record.
You can use:
IIF(ISNULL(WorkDone.Equipment),
DateAdd('m',[Inventory].[Service Period],[Inventory].[Purchase Date]),
Max(DateAdd('m',[Inventory].[Service Period],[WorkDone].[Work Date])))
AS NextServiceDate
The rest of your query can remain as is.
来源:https://stackoverflow.com/questions/49576548/syntax-of-ms-access-sql-sub-query-including-aggregate-functions