我有一个基于日期字段选择的查询。问题是这个日期字段有时是null,所以只使用'而不是null'检查null将不起作用。
这是我开发的内容:
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')
- (格式错误)也会导致数据类型不匹配异常。
然而,这就是所有数据的样子:
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] = ' '
等。他们都返回零结果。
我也尝试了下面建议的查询结构,但无济于事。
答案 0 :(得分:1)
考虑使用子查询来排除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];
注意:
GROUP BY
查询,因此不需要DISTINCT
。WHERE
子句条件(u.CHARGE_UNIT <> 'CQ'
)违背了LEFT JOIN
的目的。我不知道打算发生什么,但在我看来你也可以改用INNER JOIN
。如果[Last Modified]
也可能包含零长度字符串,请在子查询WHERE
中排除它们:
在哪里Len([上次修改])&gt; 0
或者只是使用IsDate()
:
WHERE IsDate([Last Modified]) = True
或......
WHERE IsDate(Left([Last Modified]), 10) = True
顺便说一下,您可能已经注意到[Last Modified]
作为日期/时间而不是文本数据类型会更容易。我假设你出于某种原因陷入了困境。但是,如果没有,请考虑改变它。
答案 1 :(得分: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