【问题标题】:Access SQL appears to be treating date as dd/mm/yyyy?Access SQL 似乎将日期视为 dd/mm/yyyy?
【发布时间】:2017-07-24 23:49:14
【问题描述】:

我在 MS Access 中有一个表格,其中包含员工详细信息 (tblStaff):

| Employee Number |  Employee Name |  Dept     |
------------------------------------------------
|     205147      |   Joe Bloggs   |  IT       |
|     205442      |   John Doe     |  Accounts |

我每周用新数据刷新此表,如果有任何记录发生更改(例如更改部门),那么它们将与该记录的有效日期一起存档在另一个表 (tblArchiveStaff) 中。

| Employee Number |  Employee Name |  Dept     | DateFrom | DateTo   |
----------------------------------------------------------------------
|     205147      |   Joe Bloggs   |  HR       | 03/01/16 | 01/06/17 |

我正在尝试编写一个查询,该查询将根据在给定日期有效的表从这些表中选择记录

我们可以假设 tblStaff 中的记录从 tblArchiveStaff 中该员工的最后一个条目的 dateTo + 1 开始有效,或者如果他们没有存档记录,则从 16 年 1 月 3 日开始有效。

到目前为止,我已经提出了以下查询,我已将 #07/01/2017# 的日期条件硬编码到其中:

SELECT [Employee Number], [Dept], DateFrom, DateTo
FROM 

     (
      SELECT ts.[Employee Number], ts.[Dept], nz(ta2.DateTo,#01/02/16#)+1 AS DateFrom, date() AS DateTo
      FROM tblStaff ts LEFT JOIN tblArchiveStaff ta2 ON ts.[Employee Number] = ta2.[Employee Number]

      UNION ALL

      SELECT ta.[Employee Number], ta.[Dept], ta.DateFrom, ta.DateTo
      FROM tblArchiveStaff ta

     ) AS tblUnion

WHERE #07/01/2017# BETWEEN DateFrom AND DateTo;

据我了解,上述查询应返回 2017 年 7 月 1 日有效的记录,这将是 tblStaff 中的两条记录,但它返回的是 tblArchiveStaff 中的记录。几乎就像将日期条件视为 1 月 7 日,这意味着它的格式为 dd/mm/yyyy,我认为这是不可能的。

谁能解释一下?

【问题讨论】:

  • 就像 Trevor 所说,使用中性日期格式。日期文字在 Access msdn.microsoft.com/en-us/library/aa711653(v=vs.71).aspx 中应采用美国格式,但如果不能将其解释为美国日期,Acesss 将尝试通过将其解释为 dd/mm/yyyy 日期来“提供帮助”。如果可以的话,最好使用 ISO 格式的年月日。

标签: sql ms-access


【解决方案1】:

那是因为你不遵守规则。始终将日期处理为日期值,而不是字符串,不是数字,没有例外。

因此,当您使用 Nz 甚至加 1 时,联合查询无法确定数据类型,因此它会退回以将结果作为文本返回。然后 DateFrom 变成 Text 而 DateTo 是 Date 这使得过滤成为一个疯狂的猜测。

*编辑 - 我还修改了联合查询的第一部分,以确保当前记录遵循最新的存档记录)

正确如下:

SELECT 
    tblUnion.[Employee Number], 
    tblUnion.[Dept], 
    tblUnion.DateFrom, 
    tblUnion.DateTo
FROM 
    (SELECT 
        ts.[Employee Number], 
        ts.[Dept], 
        DateAdd("d", 1, Nz(ta2.MaxDateTo, #01/02/16#)) AS DateFrom, 
        Date() AS DateTo
    FROM 
        tblStaff ts 
    LEFT JOIN 
       (SELECT 
        [Employee Number], 
        max(DateTo) AS MaxDateTo
    FROM 
        tblArchiveStaff
    GROUP BY 
       [Employee Number]) ta2 
        ON ts.[Employee Number] = ta2.[Employee Number]

    UNION ALL

    SELECT 
        ta.[Employee Number], 
        ta.[Dept], 
        ta.DateFrom, 
        ta.DateTo
    FROM 
        tblArchiveStaff ta) AS tblUnion
WHERE
    #7/1/2017# Between [DateFrom] And [DateTo];

你会得到想要的输出:

Employee Number Dept      DateFrom  DateTo
205147          IT        2017-01-07    2017-07-05
205442          Accounts  2016-01-03    2017-07-05

【讨论】:

  • 太棒了,我希望我能不止一次地投票!我完全坚持这一点,但现在你已经解释了它是完全有道理的。非常感谢!
  • 是的,这很讨厌。联合查询可能很棘手。如果您单独研究联合查询的输出,您可能已经掌握了它......默认情况下,文本是左对齐的,而日期是右对齐的。
【解决方案2】:

标准日期翻转错误。尝试在您的代码中始终使用中性日期格式,例如

d MMM yyyy

1 Jul 2017(可行但由于语言差异不推荐)

yyyy-MM-dd

2017-07-01(推荐,适用于任何地方)

【讨论】:

  • 感谢您的回复。我将如何在 SQL 代码中编写“2017 年 7 月 1 日”?我知道如果不能将其解释为 mm/dd/yyyy(例如 13/01/2017),它将解释为 dd/mm/yyyy,但我给出的示例可以读作美国日期,所以我认为它会默认那个?
  • "我将如何在 SQL 代码中编写“2017 年 7 月 1 日”?"您永远不会这样做,因为 Access 中的月份名称是本地化的。始终使用 ISO 格式:yyyy-mm-dd。它永远不会失败。
  • 恐怕我今天早上回到这个办公室尝试这个,即使使用格式 #2017/07/01# 也会返回相同的结果。我只是从 tblStaffArchive 获取记录?
猜你喜欢
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2017-07-20
  • 1970-01-01
  • 2018-03-31
相关资源
最近更新 更多