【问题标题】:How to check for dates entered mm/dd/yyyy instead of dd/mm/yyyy?如何检查输入的日期 mm/dd/yyyy 而不是 dd/mm/yyyy?
【发布时间】:2016-03-01 21:20:46
【问题描述】:

目标

我正在使用 MS Access 数据库。我需要确定用户输入错误的 DateCollected 的情况。具体来说,当用户输入 mm/dd/yyyy 而不是 dd/mm/yyyy 时。这些必须在事后找到,因为在入口点没有数据验证。

我有一个参考日期,DateEntry,我知道它是正确的,因为它带有数据库的时间戳。我已经确定了这些验证收集日期的方法:

  1. 如果日期 >12,用户不会意外将 dd/mm/yyyy 输入为 mm/dd/yyyy。
  2. DateCollected 不能在 DateEntry 之后。收集总是先发生。
  3. 查看 DateCollected 和 DateEntry 之间的分布。如果它大于 60 天,我怀疑输入错误。为了确认,我颠倒了月份和日期来创建一个 NewDate,如果重新计算的点差小于 60 天,我可以对错误进行分类。

查询

SELECT [T].[DateCollected], 
[T].[DateEntry], 
[T].[DateEntry]-[T].[DateCollected] AS Spread,
DateSerial(Year([T].[DateCollected]),Day([T].[DateCollected]),Month([T].[DateCollected])) AS NewDate, 
[T].[DateEntry]-[NewDate] AS NewSpread
FROM T
WHERE ((Day([T].[DateCollected])<=12))
ORDER BY [T].[DateEntry]-[T].[DateCollected] DESC

输出

| DateCollected |  DateEntry   | Spread |   NewDate   | NewSpread |
-------------------------------------------------------------------
|  12/02/2004   |  17/12/2004  |   309  |  02/12/2004 |    15     |
|  11/02/2009   |  03/12/2009  |   295  |  02/11/2009 |    31     |
|  12/05/2008   |  19/02/2009  |   283  |  05/12/2008 |    76     |
|  10/01/2010   |  14/10/2010  |   277  |  01/10/2010 |    13     |
|  11/12/2007   |  26/06/2008  |   198  |  12/11/2007 |    227    |
|  03/07/2007   |  20/11/2007  |   140  |  07/03/2007 |    258    |
|  12/04/2008   |  28/08/2008  |   137  |  04/12/2008 |    -98    |
|  05/06/2013   |  15/05/2013  |   -21  |  15/05/2013 |     9     |
|  01/10/2005   |  18/01/2005  |  -256  |  18/01/2005 |     8     |

问题

我在以这种方式编写查询时遇到了麻烦,因为由于某种原因,我无法将过滤器应用于 NewSpread 列。例如,我想过滤掉 NewSpread 为负数(违反上述规则#2)或 NewSpread>Spread(不是由混合 mm 和 dd 引起的)的任何情况。当我尝试包含过滤器时,例如

WHERE ((Day([T].[DateCollected])<=12)) AND (([T].[DateEntry]-[NewDate])>0)

我在询问 NewDate 的参数值时遇到错误。

问题

如何修复我的查询,以便它允许对 NewSpread 列进行过滤?

有没有更好的方法来查找输入为 mm/dd/yyyy 而不是 dd/mm/yyyy 的日期?

【问题讨论】:

  • 你能编辑你的帖子并输入确切的错误信息吗?
  • 您不能使用名称NewSpread,因为它在过滤时不存在,您必须使用完整的表达式,例如([T].[DateEntry]-[NewDate]) &gt; 10
  • 那是否意味着 NewDate 也不存在?
  • 是的,where 评估期间 NewDate 不存在

标签: sql datetime ms-access


【解决方案1】:

问题是这些表达式必须重复,即使是 [NewDate] 的表达式,因为您不能在 WHERE 子句中使用给定的别名。

但是,如果您将查询包装在另一个查询中,它会变得更容易,如下所示:

SELECT *
FROM (
    SELECT   [DateCollected], 
             [DateEntry], 
             DateDiff("d", [DateCollected], [DateEntry]) AS Spread,
             Iif(DateCollected IS NULL, 0, DateSerial(Year([DateCollected]),Day([DateCollected]),Month([DateCollected]))) AS NewDate, 
             DateDiff("d", [NewDate], [DateEntry]) AS NewSpread
    FROM     T
    WHERE    Day([DateCollected]) <= 12
) AS Main
WHERE    [Main].[NewSpread] > 0 
ORDER BY [Main].[Spread] DESC

所以现在您可以在 [NewSpread] 上执行WHERE 条件。

注意:我很惊讶地看到 [DateEntry]-[NewDate] AS NewSpread 在内部 SELECT 中工作,因为已经存在 [NewDate] 是一个别名。如果这是一个问题,那么在外部SELECT 中进行计算。

对于更复杂的查询,您甚至可能希望将外部查询本身再次包装在另一个包装 SELECT 中。

您遇到的数据类型不匹配可以通过使用DateDiff function 并计算两个日期之间的天数来规避。

如果您希望该数字包含小数,请使用分钟和除法,例如:

DateDiff("n", [DateCollected], [DateEntry])/60/24 AS Spread

【讨论】:

  • 我和你一样做了一个子查询。如果没有外部 WHERE [NewSpread] &gt;0 条件,查询工作正常。如果我包含条件,我会收到一条错误消息:标准表达式中的数据类型不匹配
  • 查看更新。我建议使用 DateDiff 函数来计算日期差异。这应该适用于比较。
  • 在 DateDiff 中“n”是否用于分钟?对我来说应该是几天。
  • 是的,我花了几分钟来确保您也能检测到较小的差异。但是,是的,使用“d”,这将是几天。答案已更新。
  • 嗯。即使使用 DateDiff 计算内部查询中的价差,当我在外部查询中包含 where 条件时,我仍然会得到 Data type mismatch in criteria expression 错误。
【解决方案2】:

您应该将parameter 定义为date。为此,请转到设计视图,打开查询参数对话框,粘贴 [您的参数] 的名称并将其数据类型设置为 Date。这样,Access 将确保它是一个有效的日期。用户将能够使用任何有效的日期格式。
另外,如果您查询 SQL Server 或 Oracle 链接表,您可能会看到性能大大提高,因为您的参数现在已正确键入
对于 2015 年 7 月 5 日这样的日期,这对您没有帮助,但您可以要求您的用户输入 2015 年 5 月 7 日。

【讨论】:

  • 是的,将来有必要拥有这样的系统。不过我的问题是已经输入的日期,并且正在寻找可以倒着输入的日期。
猜你喜欢
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
相关资源
最近更新 更多