【问题标题】:MS Access - Using time values without Date valuesMS Access - 使用没有日期值的时间值
【发布时间】:2011-10-20 01:32:29
【问题描述】:

使用表达式生成器,我构建了一个如下所示的 switch 语句:

Switch([Time]>=#12:00:00 AM# And [Time]<#7:00:00 AM#,"Before 7 am",
[Time]>=#7:00:00 AM# And [Time]<#10:00:00 AM#,"7 am - 9:59 am",
[Time]>=#10:00:00 AM# And [Time]<#5:00:00 PM#,"10 am - 4:59 pm",
[Time]>=#5:00:00 PM# And [Time]<=#9:00:00 PM#,"5 pm - 9 pm",
[Time]>#9:00:00 PM# And [Time]<#11:59:00 PM#,"After 9 pm")

但是,我注意到我的查询不正常,所以我检查了 SQL。奇怪的是,它看起来像这样:

Switch([Time]>=#12/30/1899# And [Time]<#12/30/1899 7:0:0#,"Before 7 am",
[Time]>=#12/30/1899 7:0:0# And [Time]<#12/30/1899 10:0:0#,"7 am - 9:59 am",
[Time]>=#12/30/1899 10:0:0# And [Time]<#12/30/1899 17:0:0#,"10 am - 4:59 pm",
[Time]>=#12/30/1899 17:0:0# And [Time]<=#12/30/1899 21:0:0#,"5 pm - 9 pm",
[Time]>#12/30/1899 21:0:0# And [Time]<#12/30/1899 23:59:0#,"After 9 pm") 
AS Time_Range

所以,看起来 Access 正在将这些转换为日期/时间值,但我只需要时间。有没有办法做到这一点?

【问题讨论】:

  • 为此编写一个自定义函数怎么样?我认为它会更干净。至于您的问题,实际上没有不包含某种日期部分的日期/时间之类的东西。您可能会考虑组合您的日期字段(假设您有一个),以便日期正确。理想情况下,我建议将日期和时间放在同一字段中,并为其命名,而不是 MS Access 或您正在使用的 RDBMS 中的保留字,可能类似于 DateTimeEntered。

标签: ms-access ms-access-2007


【解决方案1】:

如果您的 [Time] 字段值包含 0 作为整数(天数)部分,则该 SQL 应该可以工作。仔细检查您的 [Time] 值是否包含非零日部分。

SELECT Format([Time], "yyyy-mm-dd hh:nn:ss") AS formatted_date_time
FROM YourTable;

如果该查询显示的 [Time] 值包含 1899 年 12 月 30 日以外的日期,则可以使用 TimeValue() 函数从这些值中提取时间部分。 (有关详细信息,请参阅 Access 的帮助主题。)该功能实际上会在 1899 年 12 月 30 日为您提供一天中的同一时间,即第 0 天。正如 HK1 所提到的,没有时间数据类型(对于 VBA 或 db 引擎);只有日期/时间,并且 总是 包含一个日期值,表示为自第零天 (12/30/1899) 以来的整数天数。

编辑:如果你打算为此使用 Switch() 函数,你可以简化它。

Switch([Time]<#12/30/1899 7:0:0#,"Before 7 am",
[Time]<#12/30/1899 10:0:0#,"7 am - 9:59 am",
[Time]<#12/30/1899 17:0:0#,"10 am - 4:59 pm",
[Time]<=#12/30/1899 21:0:0#,"5 pm - 9 pm",
[Time]<#12/30/1899 23:59:0#,"After 9 pm") 
AS Time_Range

IOW,你不需要把第二个条件写成...

[Time]>=#7:00:00 AM# And [Time]<#10:00:00 AM#

...因为如果 [Time] 早于早上 7 点,第一个条件将为 True,而第二个条件不会被评估。

Edit2:您可以使用表格作为时间括号,而不是使用 Switch 语句将它们编码到您的 SQL 中。

bracket_start  bracket_end  bracket_label
12:00:00 AM     6:59:59 AM      Before 7 am
 7:00:00 AM     9:59:59 AM   7 am - 9:59 am
10:00:00 AM     4:59:59 PM  10 am - 4:59 pm
 5:00:00 PM     9:00:00 PM      5 pm - 9 pm
 9:00:01 PM    11:59:59 PM       After 9 pm

SELECT
    y.[Time],
    b.bracket_label
FROM
    YourTable AS y,
    time_brackets AS b
WHERE
        y.[Time] >= b.bracket_start
    AND y.[Time] <= b.bracket_end;

Edit3:与查询中的 Switch() 表达式相比,我更喜欢 time_brackets 表方法 (Edit2)。如果您决定更改时间括号和/或括号标签,如果您有多个这样的查询,则表格方法将更容易维护。只需更改 time_brackets 表,而不是在每个查询中修改 Switch() 表达式。

如果您只是针对单个查询执行此操作,那么这种考虑可能不会令人信服。但是,在这种情况下,我仍然更喜欢表格方法,因为我发现编写复杂的 Switch() 表达式且无错误更具挑战性。如果我们考虑使用嵌套的 IIf() 表达式而不是 Switch(),同样的论点也将适用(甚至更是如此!)。

最后,括号时间范围和标签构成数据。数据理所当然地属于表格。只要可行,我宁愿避免将数据编码到 SELECT 语句中。这意味着我想方设法避免在查询中使用 Switch() 或嵌套的 IIf() 表达式。这里附带的一个好处是查询设计器不会像没有 Switch() 语句时那样重写您的 Switch() 语句。 :-)

【讨论】:

  • 我尝试了第一种方法,效果很好。谢谢汉斯!
【解决方案2】:

这里有一些额外的建议...

如果您的 [Time] 值可能包含除零以外的整数(天)部分,您可以尝试以下@HansUp 建议的变体:

Switch(Hour([Time])<7,"Before 7 am",
Hour([Time])<10,"7 am - 9:59 am",
Hour([Time])<17,"10 am - 4:59 pm",
Hour([Time])<=21,"5 pm - 9 pm",
Hour([Time])<=23,"After 9 pm") 
AS Time_Range

或者,如果您想强制假设 [Time] 值包含整数部分,您可以在基础表中设置字段的“验证规则”属性(如果有的话)到:

>=0 And <1

【讨论】:

  • 因为否则“日期”值可以分配小于零的值。负数是可能的——它们只代表 1899 年 12 月 30 日之前的几天。
猜你喜欢
  • 2020-10-23
  • 2014-11-30
  • 1970-01-01
  • 2016-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-23
  • 1970-01-01
相关资源
最近更新 更多