1

我有一个查询,它的选择基于日期字段。问题是该日期字段有时为空,因此仅使用“而不是空”检查是否为空是行不通的。

这是我开发的:

SELECT DISTINCT WS_ALL_OBJ.[Owner ID], Users.CHARGE_UNIT, WS_ALL_OBJ.[Owner Name]
FROM WS_ALL_OBJ LEFT JOIN Users ON WS_ALL_OBJ.[Owner ID] = Users.CNAME
WHERE 
    (IIF(IsNull(WS_ALL_OBJ.[Last Modified]), DateValue('2050-12-01'), DateValue(Left(WS_ALL_OBJ.[Last Modified], 10))) < #2012-11-26#
   And 
    (Users.CHARGE_UNIT <> 'CQ'))
GROUP BY WS_ALL_OBJ.[Owner ID], Users.CHARGE_UNIT, WS_ALL_OBJ.[Owner Name];

运行此查询时,它会引发“标准表达式中的数据类型不匹配”错误消息。

我已经把它缩小到这行代码——DateValue(Left(WS_ALL_OBJ.[Last Modified], 10))因为如果我替换它DateValue('2011-11-26')——它工作得很好。

起初我以为是因为我的字段中有空值,Last Modified这就是我想出这个的原因 -(IIF(IsNull(WS_ALL_OBJ.[Last Modified]), DateValue('2050-12-01'), DateValue(Left(WS_ALL_OBJ.[Last Modified], 10))) < #2012-11-26#

那不应该解决空值问题吗?

另一种可能性是来自的字符串Left()格式不正确。我认为这是因为这个 - DateValue('2011-11026')- (格式错误)也会通过 Data Type Mismatch 异常。

然而,这就是所有数据的样子:

2008-01-18 13:10:54 CST

它存储为“文本”字段,来自链接的 csv 文件。该Left()函数应采用前 10 个字符并传递给DateValue()

我很茫然,感谢任何帮助。

更新:我也试过cdate(Left(WS_ALL_OBJ.[Last Modified], 10))并得到同样的错误。我还修改为使用 `(IsNull(WS_ALL_OBJ.[Last Modified]) 或 WS_ALL_OBJ.[Last Modified] = '') 检查空字符串

我最终运行了一些查询,以确保不存在WS_ALL_OBJ.[Last Modified] = ''WS_ALL_OBJ.[Last Modified] = ' '类似的存在。他们都返回零结果。

我也尝试了下面建议的查询结构,但无济于事。

4

2 回答 2

1

考虑一个子查询来排除Null的WS_ALL_OBJ行。[Last Modified]这样可以避免尝试将 Null 转换为日期/时间值时发生的错误。

SELECT
    w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name]
FROM
    (
        SELECT [Owner ID], [Owner Name], [Last Modified]
        FROM WS_ALL_OBJ
        WHERE [Last Modified] Is Not Null
    ) AS w
    LEFT JOIN Users AS u
    ON w.[Owner ID] = u.CNAME
WHERE 
        DateValue(Left(w.[Last Modified], 10)) < #2012-11-26#
    AND u.CHARGE_UNIT <> 'CQ'
GROUP BY w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name];

笔记:

  1. 我为表名使用了别名,因为这使我的大脑更容易消化 SQL。
  2. 由于这是一个GROUP BY查询,DISTINCT因此不需要。
  3. WHERE子句条件 ( u.CHARGE_UNIT <> 'CQ') 违背了LEFT JOIN. 我不知道打算发生什么,但在我看来,您不妨INNER JOIN改用它。
  4. 如果[Last Modified]还可能包含零长度字符串,请在子查询中排除它们WHERE

    WHERE Len([上次修改时间]) > 0

或者也许只是使用IsDate()

WHERE IsDate([Last Modified]) = True

或者 ...

WHERE IsDate(Left([Last Modified]), 10) = True

顺便说一句,您可能已经注意到使用[Last Modified]日期/时间而不是文本数据类型会更容易。我假设您出于某种原因被文本困住了。但是,如果没有,请考虑更改它。

于 2013-02-26T16:16:23.797 回答
0

以下是我通常的处理方式。我冒昧地使用别名来缩短 SQL 并使其更具可读性。我强烈建议不要在字段名称中使用空格。如果您停止这种做法,您就不必担心使用括号。

我还猜测您将日期值存储为字符串。我通常会尽量避免这种情况。我认为在大多数情况下,最好在需要时将日期值转换为字符串,而不是相反。

确保将以下函数中的 vDate 参数保留为变体数据类型。如果您将其更改为字符串或日期,它将不允许您处理空值。您的 SQL 不会产生错误,而是会产生非常奇怪的结果。

你确定你的日期总是 10 个字符吗?日期值可以不用前导零来表示,这会使它们更短。

SELECT DISTINCT w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name]
FROM WS_ALL_OBJ as w LEFT JOIN Users as u ON w.[Owner ID] = u.CNAME
WHERE 
    GetLastModDate(w.[Last Modified]) < #2012-11-26#
   And 
    u.CHARGE_UNIT <> 'CQ'
GROUP BY w.[Owner ID], u.CHARGE_UNIT, w.[Owner Name];


'Put this code in a VBA Module
Public Function GetLastModDate(vDate) as Date
    If Nz(vDate, "") = "" Then
        GetLastModDate = #01/12/2050#
    Else
        GetLastModDate = DateValue(Left(vDate), 10)
        End If
End Function
于 2013-02-26T16:04:30.320 回答