2011-10-18 34 views
1

使用表達式生成器,我建了一個switch語句看起來像這樣:的MS Access - 使用時間值沒有日期值

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 

因此,它看起來像訪問被轉換到這些日期/時間值,但我只需要時間。有沒有辦法做到這一點?

+1

什麼寫作t的自定義函數他呢?我認爲它會更乾淨。至於你的問題,真的沒有日期/時間這樣的東西不包含某種日期部分。您可以考慮合併您的日期字段(假設您有),以便日期正確。理想情況下,我建議將日期和時間放在同一個字段中,併爲其指定一個不是MS Access中的保留字或您正在使用的RDBMS的名稱,可能類似於DateTimeEntered。 – HK1

回答

6

如果您的[時間]字段值包含0作爲整數(天數)部分,那麼SQL應該可以工作。仔細檢查您的[時間]值是否包含非零日組件。

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

如果該查詢顯示了[時間],其包括比其他12/30/1899一個日期值,則可以使用TIMEVALUE()函數從這些值中提取的時間部分。 (有關詳細信息,請參閱訪問'幫助主題。)該功能實際上會在一天中的同一時間爲零日,即零日。正如HK1所提到的,不存在時間數據類型(無論是VBA還是數據庫引擎);只有日期/時間,且總是包括表示爲從第零天(12/30/1899)起的整數天數的日值。

編輯:如果你要使用此交換機()函數,可以將其簡化。

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 

督察,你不需要寫第二個條件是......

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

...因爲如果[時間]早於7日凌晨,第一個條件是真,第二個條件不會被評估。

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:我寧願在查詢中的開關()表達time_brackets表方法(EDIT 2)。如果在您決定更改時間括號和/或括號標籤的情況下,如果您有多個此類查詢,則表格方法將更易於維護。只需更改time_brackets表,而不是在每個查詢中修改Switch()表達式。

如果您只爲單個查詢執行此操作,那麼這種考慮可能不會引人注目。但是,在這種情況下,我仍然更喜歡錶格方式,因爲我發現編寫無錯誤的複雜Switch()表達式更具挑戰性。如果我們考慮一個嵌套的IIf()表達式而不是Switch(),那麼同樣的論點也適用(甚至更多!)。

最後,括號時間範圍和標籤構成數據。數據正確地屬於表格。無論哪種情況,我都希望避免將數據編碼到SELECT語句中。這意味着我尋找避免查詢中的Switch()或嵌套的IIf()表達式的方法。這裏的附帶好處是,查詢設計人員不會像在沒有Switch()語句時那樣重寫您的Switch()語句。 :-)

+0

我嘗試了第一種方法,它完美地工作。謝謝漢斯! – jerry

1

這裏有一些額外的建議...

如果你的[時間]值可能包含一個整數(一天)成分爲零以外,你可以嘗試@ 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 

另外,如果你想執行的假設該[時間]值包含整數部分,你可能會設置字段的「有效性規則」屬性在基礎表(如果有的話)到:

>=0 And <1 
+1

因爲否則可以爲「日期」值分配小於零的值。負數可能 - 它們僅代表1899年12月30日之前的日子。 –