MS Access/SQL 子查询的语法,包括聚合函数

Posted

技术标签:

【中文标题】MS Access/SQL 子查询的语法,包括聚合函数【英文标题】:Syntax of MS Access/SQL sub-query including aggregate functions 【发布时间】:2018-03-30 14:49:05 【问题描述】:

我正在尝试创建一个数据库来管理设备的维护。我有两张桌子:

    一个(库存)包含每件设备的详细信息,包括购买日期服务期限, 包含已完成工作的详细信息 (WorkDone),包括执行工作的日期 (Work Date)。

我想要一个显示下次维修日期的查询。到目前为止,我有:

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

只要已为给定的设备注册了某些已完成的工作,此方法就可以正常工作。如果没有进行任何工作,我希望 NextServiceDate 也显示

DateAdd('m',[Inventory].[Service Period], [Inventory].[Purchase Date])

但是,我无法弄清楚如何获取 SQL/MS 访问权限以比较两个值并仅显示两者中的较大值。通过阅读,我认为我应该能够进行子查询,但我无法弄清楚如何分阶段进行。

我一直在尝试从这里改编@MikeTeeVee 的答案:Is there a Max function in SQL Server that takes two values like Math.Max in .NET?。但是我不断收到错误消息,说查询不是聚合函数的一部分,我不确定我做错了什么。例如,我试过:

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

其中有一些语法错误。

【问题讨论】:

【参考方案1】:

考虑使用 LEFT JOIN 返回匹配或不匹配的记录,其中后者填充 NULL,然后使用 NZ() 运行聚合 MAX

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

【讨论】:

编辑:实际上我还有一个问题,因为我不想应用标准:我想返回 NextServiceDate 早于一周时间的所有条目。我试过:HAVING Max(NZ(DateAdd('m', i.[Service Period], w.[Work Date]), DateAdd('m', i.[Service Period], i.[Purchase Date]))) < DateAdd('ww',1,Date()) 但这只是比较日期的 Day 部分。例如,今天是 31/3/18,因此它显示了在任何月份的前 6 天具有 NextServiceDate 的所有条目。 (我有一个英国系统,所以日期格式是 dd/mm/yyyy,以防万一影响事情)。【参考方案2】:

您不必比较两个日期,只需检查是否存在 WorkDone 记录以匹配 Inventory 记录。

你可以使用:

IIF(ISNULL(WorkDone.Equipment),
DateAdd('m',[Inventory].[Service Period],[Inventory].[Purchase Date]),
Max(DateAdd('m',[Inventory].[Service Period],[WorkDone].[Work Date])))
AS NextServiceDate

您的查询的其余部分可以保持原样。

【讨论】:

这给了我一个错误提示:“您的查询不包括指定的表达式 'IIF(ISNULL(WorkDone.Equipment), DateAdd('m',[Inventory].[Service Period],[ Inventory].[Purchase Date]), Max(DateAdd('m',[Inventory].[Service Period],[WorkDone].[Work Date])))' 作为聚合函数的一部分。" 只要使用MAX(IIF(...)) AS.NextServiceDate

以上是关于MS Access/SQL 子查询的语法,包括聚合函数的主要内容,如果未能解决你的问题,请参考以下文章

MS Access SQL:聚合最小值但检索其他字段

将 SQL Server 代码转换为 MS Access SQL 代码 - DISTINCT 问题 [重复]

如何在WHERE子句中使用MS Access SQL子查询来替换长OR表达式

MS Access SQL 语法错误

MS Access SQL 转换对枢轴值的聚合操作

MS Access SQL 运行总数