我正在尝试从 (NVARCHAR) 列之一在数字范围内的表中选择行。
SELECT ID, Value
FROM Data
WHERE ISNUMERIC(Value) = 1 AND CONVERT(FLOAT, Value) < 66.6
不幸的是,作为 SQL 规范的一部分,AND 子句不必短路(在 MSSQL Server EE 2008 上也不必)。更多信息:是否评估了 SQL WHERE 子句短路?
我的下一个尝试是尝试这个,看看我是否可以实现对 CONVERT 的延迟评估
SELECT ID, Value
FROM Data
WHERE (CASE WHEN ISNUMERIC(Value) = 1 THEN CONVERT(FLOAT, Value) < 66.6 ELSE 0 END)
但我似乎无法将 < (或任何比较)与 CONVERT 的结果一起使用。它因错误而失败
Incorrect syntax near '<'.
我可以逃脱
SELECT ID, CONVERT(FLOAT, Value) AS Value
FROM Data
WHERE ISNUMERIC(Value) = 1
因此,显而易见的解决方案是将整个 select 语句包装在另一个 SELECT 和 WHERE 中,并从内部选择返回转换后的值,并在外部选择的位置进行过滤。不幸的是,这就是我的 Linq-to-sql 问题出现的地方。我不仅按一个范围过滤,而且按许多可能进行过滤,或者只是按记录的存在(有一些日期范围选择和比较我已经遗漏了。 )
本质上我希望能够生成这样的东西:
SELECT ID, TypeID, Value
FROM Data
WHERE (TypeID = 4 AND ISNUMERIC(Value) AND CONVERT(Float, Value) < 66.6)
OR (TypeID = 8 AND ISNUMERIC(Value) AND CONVERT(Float, Value) > 99)
OR (TypeID = 9)
(在每个 where 选项中都有一些其他子句。)如果我在内部选择中过滤掉非 ISNUMERIC 值,这显然不起作用。
正如我提到的,我正在使用 Linq-to-sql(和 PredicateBulider)来构建这些查询,但不幸的是
Datas.Where(x => ISNUMERIC(x.Value) ? Convert.ToDouble(x.Value) < 66.6 : false)
被转换成这会导致最初的问题失败。
WHERE (ISNUMERIC([t0].[Value]) = 1) AND ((CONVERT(Float,[t0].[Value])) < @p0)
对于每个比较,我最后的手段必须是针对同一张表上的双重选择进行外部连接,但这并不是一个真正的想法解决方案。我想知道是否有人以前遇到过类似的问题?