在 nvarchar 列上使用 between 子句查找范围不起作用

Using between clause on nvarchar column to find range is not working

我有 3 个 nvarchar 列 user_3、user_4 和描述。我正在设置是和否标志。如果描述列中的值等于或介于 user_3 和 User4 之间,则将标志设置为 'N' 否则 将标志设置为 'Y'.

这是我目前编写的 SQL 脚本。它在某些情况下有效,但并非总是如此。查看带有结果的图像。例如,它在第 1 行有效,但在第 6 行无效。我做错了什么?

SELECT  [B].USER_3,[B].USER_4,A.DESCRIPTION,
(case when Isnumeric(A.DESCRIPTION) <> 1 then 'Y' 
else case when (CASE WHEN Isnumeric(A.DESCRIPTION) = 1 then
cast(A.DESCRIPTION AS decimal(10,5)) else 0 end) 
between ( CASE WHEN Isnumeric([B].USER_4) = 1 then 
cast([B].USER_4 AS decimal(10,5)) else 0 end) and
(CASE WHEN Isnumeric([B].USER_3) = 1 then cast([B].USER_3  AS decimal(10,5)) else 0 end)
then 'N' else 'Y' end end) as Flagset
from A , B

这是结果的屏幕截图

enter image description here

问题出在您根据 docs 使用 BETWEEN:

BETWEEN returns TRUE if the value of test_expression is greater than or equal to the value of begin_expression and less than or equal to the value of end_expression.

因为不知道USER_3USER_4是上限还是下限,所以需要两个都测试

注意:对于这种查询,我更愿意预先计算我需要的所有值(在本例中使用 CROSS APPLY)。它使跟踪和调试变得更加容易。

SELECT USER_3, USER_4, [DESCRIPTION]

    , CASE WHEN ISNUMERIC([DESCRIPTION]) <> 1 THEN 'Y' ELSE
        CASE WHEN CASE WHEN ISNUMERIC([DESCRIPTION]) = 1 THEN CAST([DESCRIPTION] AS decimal(10,5)) ELSE 0 END BETWEEN CASE WHEN ISNUMERIC(USER_4) = 1 THEN CAST(USER_4 AS decimal(10,5)) ELSE 0 END AND
        CASE WHEN ISNUMERIC(USER_3) = 1 THEN CAST(USER_3  AS decimal(10,5)) ELSE 0 END
    THEN 'N' ELSE 'Y' END END AS Flagset

    , CASE WHEN DNUMERIC <> 1 THEN 'Y' ELSE CASE WHEN DESCRIPTIOND BETWEEN USER_4D AND USER_3D OR DESCRIPTIOND BETWEEN USER_3D AND USER_4D THEN 'N' ELSE 'Y' END END CorrectedFlagSet

FROM (VALUES
    ('1.395','1.385','1.390')
    , ('22.025','41.425','22')
    , ('22.025','41.425','23.025')
) AS X (USER_3, USER_4, [DESCRIPTION])
CROSS APPLY (VALUES (
    CASE WHEN ISNUMERIC(USER_3) = 1 THEN CAST(USER_3 AS decimal(10,5)) ELSE 0 END
    , CASE WHEN ISNUMERIC(USER_4) = 1 THEN CAST(USER_4 AS decimal(10,5)) ELSE 0 END
    , CASE WHEN ISNUMERIC([DESCRIPTION]) = 1 THEN CAST([DESCRIPTION] AS decimal(10,5)) ELSE 0 END
    , CASE WHEN ISNUMERIC([DESCRIPTION]) = 1 THEN 1 ELSE 0 END
)) AS Y (USER_3D, USER_4D, DESCRIPTIOND, DNUMERIC);

Returns:

USER_3 USER_4 DESCRIPTION Flagset CorrectedFlagSet
1.395 1.385 1.390 N N
22.025 41.425 22 Y Y
22.025 41.425 23.025 Y N

我敢肯定,我不必提及您真的应该首先以数字形式存储这些数据,因为它会更好地执行并为您节省很多未来的问题。

布局合理且大小写一致的查询也有助于理解和调试它们。

最后提供一个最小的可重现示例,其中包含示例数据、您的查询和您想要的结果(如此处所示)可以让人们更轻松地提供帮助。