2009-10-06 53 views
0

我跑Access 2003中我使用交換機根據布爾標準來選擇日期字段:訪問2003年SQL開關打破數據類型?

Switch(<criterion>, Date1, 1, Date2) 

即,如果「標準」爲真,則返回日期1,否則返回日期2。

Date1和Date2是表中的日期/時間類型列。

問題是,Switch將它們返回爲文本 - 不是日期/時間!

有沒有辦法強制他們進入日期?我試圖

Switch(<criterion>, #Date1#, 1, #Date2#) 

而且

Switch(<criterion>, Val(Date1), 1, Val(Date2)) 

這兩者的失敗,一個錯誤信息或其他。

任何想法?

回答

2

我認爲即時如果[IIF()函數是你要怎樣做更好的匹配:

IIf(<criterion>, Date1, Date2) 

但開關()函數不應該打破的數據類型,併爲與日期/時間數據類型不兼容。考慮一下這個功能:

Public Function trySwitch(ByVal pWhichDay As String) As Variant 
    Dim varOut As Variant 
    varOut = Switch(pWhichDay = "yesterday", Date - 1, _ 
     pWhichDay = "today", Date, _ 
     pWhichDay = "tomorrow", Date + 1) 
    trySwitch = varOut 
End Function 

trySwitch( 「今天」)回報10/6/2009類型名(trySwitch( 「今天」))回報日期

+0

我同意嘗試IIF() – CRice 2009-10-07 01:45:02

+0

大衛和onedaywhen雖然有趣的解釋,儘管如此,IIf的工作(我真的應該一直在使用它)首先看到我的評論onedaywhen的答案更多細節的差異,但現在,我只使用IIf – mikeh 2009-10-07 16:14:55

1

有一些奇怪用你的例子。

Switch接受表達式對,並且如果第一個計算結果爲True,則返回其配對值,否則傳遞給第二個計算表達式並評估該參數。

你似乎在治療1爲True,這是因爲它不是費爾斯,但你會用更好:

Switch(<criterion>, Date1, True, Date2) 

但是,這只是一個立即如果函數的功能複製,IIf()和IIf()的參數較少。

但它有同樣的問題,因爲它返回一個變體。但是,您應該能夠將其強制爲可以格式化爲Date的數據類型。

但是否該變體將被隱式強制或者需要明確執行,取決於您使用它的位置。在查詢結果中,可以將來自IIf([criteria],Date1,Date2)的輸出作爲日期進行排序,因爲該列被強制轉換爲日期類型。

如果您必須明確地執行強制轉換,則需要使用CDate()函數 - 您將使用CDate()函數包裝產生Variant輸出的外部函數,以確保變體輸出是明確強制轉換日期類型:

CDate(IIf(<criterion>, Date1, Date2)) 

但我很可能是失去了一些東西很重要,因爲我似乎被關閉了完全不同的軌跡......

+0

有趣的是:當我將Date2包裝在Switch的CDate()中時,Access將結果集列視爲非日期類型(請參閱我對onedaywhen的評論)。將整個Switch語句包裝在CDate中,它將列視爲日期類型(按照相同的排序/單元對齊標準)。即「Switch(,Date1,True,CDate(Date2))」與類型不等效於「 CDate(Switch(,Date1,True,Date2))「[注意:這裏的IIf仍然更好,因爲Date1爲空時返回Null,而Switch看到Null Date1並返回#錯誤#,弄髒結果集] – mikeh 2009-10-07 16:23:32

+0

我並不是建議強制傳遞參數,因爲那些顯然在那時具有正確的數據類型。正如你所發現的那樣,你必須強制使用正確的數據類型是Switch()或IIf()的Variant輸出。我會編輯以使其更清晰。 – 2009-10-09 01:17:06

1

你可以張貼一些代碼和數據請重現問題?由於這是在SQL代碼SWITCH()那麼我認爲SQL DDL(CREATE TABLE等)和DML(INSERT INTO添加數據)將是最合適:)

[挑剔點:Access數據庫SQL沒有一個「布爾」數據類型。它有一個YESNO數據類型,它可以是NULL的值;三值邏輯不是布爾]

下面是一些SQL DML(ANSI-92 Query Mode語法)來演示運行方式如預期的我:

SELECT TYPENAME 
     (
      SWITCH 
      (
      NULL, #2009-01-01 00:00:00#, 
      FALSE, #2009-06-15 12:00:00#, 
      TRUE, #2009-12-31 23:59:59# 
     ) 
     ); 

改變任何「條件」值和值總是作爲'日期'返回,即DATETIME


UPDATE:

TYPENAME功能是一個偉大的 工具...訪問似乎解釋的結果集的 整個 「列」 不同

確實。由於列只能是一種數據類型,因此行中的結果爲TYPENAME()可能會引起誤解。混合類型的行值必須「提升」爲更高的數據類型。與Access數據庫引擎通常一樣,這個過程完全不透明,關於這個主題的文檔完全沒有,所以你只需要吮吸它就可以看到例如

SELECT #2009-01-01 00:00:00# AS row_value, 
     TYPENAME(#2009-01-01 00:00:00#) AS row_type 
    FROM Customers 
UNION ALL 
SELECT 0.5, 
     TYPENAME(0.5) AS row_type 
    FROM Customers 

分別返回'Date'和'Decimal',但列將是什麼?顯然,答案是:

SELECT DT1.row_value, TYPENAME(DT1.row_value) AS column_type 
    FROM (
     SELECT DISTINCT #2009-01-01 00:00:00# AS row_value 
      FROM Customers 
     UNION ALL 
     SELECT DISTINCT 0.5 
      FROM Customers 
     ) AS DT1; 

'String'?!

......這當然不是Access數據庫引擎SQL數據類型。因此,令人煩惱的是,TYPENAME()使用了「最適合」VBA類型的名稱。例如:

SELECT TYPENAME(CBOOL(0)); 

返回'布爾',即使如上所述,Access數據庫引擎SQL中沒有布爾數據類型。並且

SELECT TYPENAME(my_binary_col) 

返回'String'。注意,相同的VBA映射限制適用於功能(又一個煩惱),例如沒有'投到BINARY'功能,並且自從Jet 4以來CDEC()功能仍然中斷。0 :(

+0

TYPENAME函數是一個很好的工具 - +1和有用的疑難解答提示。它告訴我,我的值是'Date'和'Null'(對於Null條目,顯然),並且每行的類型結果在IIf表達式和Switch表達式中是相同的。但是Access似乎以不同的方式解釋了結果集的整個「列」:對於IIf,Date(時間可排序,右對齊),以及Switch的其他內容(僅用於詞彙排序,左對齊)。 – mikeh 2009-10-07 16:14:06

+0

這是因爲當True和False部分的類型爲Date時,IIf()將返回值強制爲子類型Date()的Variant。 Switch()不這樣做 - 它只是返回一個變體(可能是子類型String),並且必須用CDate()明確強制。 – 2009-10-09 01:22:29

+0

@David W. Fenton:記住我們正在討論Access數據庫SQL中使用的表達式,儘管TYPENAME()可能會告訴你,但它沒有Variant或String數據類型。 – onedaywhen 2009-10-12 08:45:14