MS Access 根据给定的日期范围选择查询字段

Posted

技术标签:

【中文标题】MS Access 根据给定的日期范围选择查询字段【英文标题】:MS Access Select Query fields based on date range given 【发布时间】:2011-06-24 21:40:44 【问题描述】:

我已经接管了一家诊所的 Access 2003 数据库的管理工作。不幸的是,创建数据库的人对数据库知之甚少,并将所有内容都放在一个巨大的表中。所以现在我有一个名为 All Clinic Data 的表,其中包含以下字段(以及大约 40 个其他字段):PatientID, First Name, Last Name, Appt Date, OB at Appt, Billing Item #1, Second Appt Date, Reason for Second Appt, OB at Second Appt, Billing Item #2.

我知道这不是安排数据的最佳方式,并且计划在未来对数据库进行全面检修。但是,现在我需要创建仅包含特定日期范围内发生的约会信息的报告。

这是我目前用来填充我的报告的 SQL 查询,但如果其中一个在给定的日期范围内,它会从表中捕获患者的所有约会。

SELECT 
    Format([Input start date],"mm/dd/yy") & " through " & Format([Input end date],"mm/dd/yy") AS Expr1, 
    [All Clinic Data].[PatientID], [All Clinic Data].[Last Name], 
    [All Clinic Data].[First Name], [All Clinic Data].[Appt Date], 
    [All Clinic Data].[OB at Appt], [All Clinic Data].[Billing Item #1], 
    [All Clinic Data].[Second Appt Date], [All Clinic Data].[Reason for Second Appt], 
    [All Clinic Data].[OB at Second Appt], [All Clinic Data].[Billing Item #2] 
FROM [All Clinic Data]
WHERE (
        (([All Clinic Data].[Appt Date])>[Input start date] And 
        ([All Clinic Data].[Appt Date])<[Input end date])
    ) 
    OR 
    (
        (([All Clinic Data].[Second Appt Date])>[Input start date] And 
        ([All Clinic Data].[Second Appt Date])<[Input end date])
    ) 
ORDER BY [All Clinic Data].[Last Name];

注意输入开始日期和输入结束日期是查询运行时输入的参数。 我曾尝试使用 IIF 删除多余的数据,但我不知道如何构建报表,以便它仅显示给定日期范围内的预约日期和相关数据(OB 和计费项目)。

例子:

1, Sally, Jones, 1/04/2010, Dr.A, 2/05/2011, Dr. B, Flu

2, Jennifer, Baker, 7/05/2010, Dr.X, 15/05/2011, Dr. B, Checkup

3, Joe, Smith, 20/06/2010, Dr.S, 

4, Tina, Turner, 17/05/2010, Dr.X, 15/06/2011, Dr. B, Checkup 

如果 [输入开始日期] = 2010 年 5 月 1 日且 [输入结束日期] = 2010 年 5 月 31 日

我希望我的报告包含:

Sally, Jones, 

 1. 2/05/2011, Dr. B, Flu

Jennifer, Baker, 

 1. 7/05/2010, Dr.X  
 2. 15/05/2011, Dr.B, Checkup

Tina, Turner, 

 1. 17/05/2010, Dr.X

我希望这是足够的信息。感谢您的帮助。

更新 1 这是我尝试下面迈克建议的第一步。我使用 phn 作为稍后将获取的患者信息的标识符。我遇到了编译错误,而且我不够老练,无法知道自己做错了什么。有什么想法吗?

SELECT 
    Format([Input start date],"mm/dd/yy") & " through " & Format([Input end     date],"mm/dd/yy") AS Expr1, 
    [All Clinic Data].PHN AS Phn, [All Clinic Data].[Appt Date] AS Date, 
    [All Clinic Data].[OB at Appt] AS OBName, 
    [All Clinic Data].[Billing Item #1] AS Billing 
FROM [All Clinic Data]

WHERE ([All Clinic Data].[Appt Date]>[Input start date] And [All Clinic Data].[Appt Date]<[Input end date])

UNION

SELECT 
    Format([Input start date],"mm/dd/yy") & " through " & Format([Input end date],"mm/dd/yy") AS Expr1, 
    [All Clinic Data].PHN AS Phn, [All Clinic Data].[Second Appt Date] AS Date, 
    [All Clinic Data].[OB at Second App] AS OBName, 
    [All Clinic Data].[Billing Item #2] AS Billing FROM [All Clinic Data]

WHERE ([All Clinic Data].[Second Appt Date]>[Input start date] And [All Clinic Data].[Second Appt Date]<[Input end date]);

【问题讨论】:

您要求在 MM/DD/YYYY 和 MM/DD/YYYY 之间进行约会,但数据似乎存储为 DD/MM/YYYY。你能确认一下吗? 是的,我的数据存储为 DD/MM/YYYY。在我的报告中,我将其格式化为 MM/DD/YY。我在示例中长期输入了我的输入参数,据我所知,Access 为我将其转换为 DD/MM/YYYY,以便它可以进行比较。 我现在没有时间浏览它并测试代码,但我认为这是我要研究的方法: 1. 创建一个查询以选择您想要的每个人的第一个约会信息. 2. 创建查询以选择所有第二个约会信息。 3.将这两者结合起来并从中选择。将有分组问题需要解决。 HTH。 【参考方案1】:

创建一个名为PatientAppointment的查询:

SELECT
   D.PatientID,
   D.[Appt Date] AS ApptDate,
   D.[OB at Appt] AS OBName
   D.[Billing Item #1] AS Billing 
UNION ALL SELECT
   D.PatientID,
   D.[Second Appt Date],
   D.[OB at Second Appt],
   D.[Billing Item #2];

请注意,无法在设计器中编辑此查询。您只能在 SQL 视图中使用它。然后,将此查询用作对此数据的所有查询的来源:

SELECT *
FROM
   PatientAppointment PA
WHERE
    PA.ApptDate >= [Input start date]
    AND PA.ApptDate < [Input end date];

我不知道性能如何,但您可以尝试并告诉我们。基本上,将其视为您的约会表,甚至不处理主表中的这些列。这将是您慢慢开始更改应用程序的一种方式,因为最终您可以将其设为实际表并迁移数据。

这是一个可能的替代解决方案,可以,让我强调可以更好。或者更糟:

创建一个表,其中包含一列和一行。表或行的名称无关紧要,但将数据类型设为数字 Long。我假设您将此表命名为Dual。然后进行同样的PatientAppointment查询:

SELECT
    D.PatientID,
    Iif(A.ApptNum = 1, D.[Appt Date], D.[Second Appt Date]) ApptDate,
    Iif(A.ApptNum = 1, D.[OB at Appt], D.[OB at Second Appt]) OBName,
    Iif(A.ApptNum = 1, D.[Billing Item #1], D.[Billing Item #2]) Billing
FROM
   [All Clinic Data] D
   INNER JOIN [
      SELECT 1 AS ApptNum FROM Dual
      UNION ALL SELECT 2 FROM Dual
   ]. A ON 1 = 1

如果您在数据库中打开了“SQL 92 语法”,请告诉我,我将在最终查询中切换到更好的语法。

您也可以按照 cmets 中的建议执行 UNION ALL SELECT 方法(我建议不要只使用 UNION SELECT,因为这会使引擎做更多的工作来消除重复项)。我无法立即发现您的查询有任何问题,请单独尝试每个单独的 SELECT 语句,看看是否有问题。

最后,如果您使用这些方法中的任何一种方法的性能太差,那么将我的Dual 查询与您的给定查询混合起来就可以解决问题。使用大 OR 条件执行查询,但将两个约会拆分为单独的行,如上面的 Dual 查询中所示。您需要添加一个附加条件来抑制与正确日期范围不匹配的行(因为其他约会已经匹配)。

【讨论】:

以上是关于MS Access 根据给定的日期范围选择查询字段的主要内容,如果未能解决你的问题,请参考以下文章

MS Access:从日期时间值返回特定日期的查询

MS Access 日期范围函数减慢查询速度

基于控件名称而不是控件源(字段)的 MS Access 计算

从 Access 中的日期时间字段中选择时间范围

未找到最后日期时的 MS Access 查询日期范围

根据日期仅选择每条记录的最新版本 | MS Access [重复]