Sql server 查询求值路径

Sql server 查询求值路径,sql-server,sql-server-2014,Sql Server,Sql Server 2014,更新:两个查询的顺序错误。第一个有效,第二个无效 我遇到了一些奇怪的SQL Server行为,这让我很困惑,我希望有人能帮我弄清楚到底发生了什么 我的查询需要从许多表中提取数据,包括products表。我们使用的模式非常严格,最近我们添加了一些新产品,这些产品的名称中包含“重复”值(即,我们每3、6或12个月向客户开具一次账单,并且该数字仅在产品名称中的文本中可用。这是有意义的,但事实就是如此) 我添加了一个WHERE子句来过滤掉3种特定的产品,然后运行以下代码以获得数量重复因子: CAST(R

更新:两个查询的顺序错误。第一个有效,第二个无效

我遇到了一些奇怪的SQL Server行为,这让我很困惑,我希望有人能帮我弄清楚到底发生了什么

我的查询需要从许多表中提取数据,包括products表。我们使用的模式非常严格,最近我们添加了一些新产品,这些产品的名称中包含“重复”值(即,我们每3、6或12个月向客户开具一次账单,并且该数字仅在产品名称中的文本中可用。这是有意义的,但事实就是如此)

我添加了一个
WHERE
子句来过滤掉3种特定的产品,然后运行以下代码以获得数量重复因子:

CAST(RTRIM(SUBSTRING(e.NAME, CHARINDEX('-', e.NAME) +2 , 2)) as int)
没什么特别的,WHERE条款专门过滤了这3种产品,我们应该很好。然后,我将检索到的值转换为一个整数,以便在计算中使用

然而,看起来是随机的,查询会抱怨两个字母组合无法转换为int值

我的假设是,通过使用WHERE子句删除不需要的产品,其他产品从一开始就不会被评估。如果上述代码是查询中的唯一内容,则查询将运行。如果我们添加
e.NAME
作为唯一的其他字段,我会得到一个错误:

Conversion failed when converting the nvarchar value 'ni' to data type int.
我还试图通过将产品硬编码到联接中来过滤掉不需要的产品(这其实并不重要),但没有帮助

执行计划和更新表上的统计数据并没有显示任何有价值的东西

这将抛出错误:

SELECT
    CAST(RTRIM(SUBSTRING(e.NAME, CHARINDEX('-', e.NAME) +2 , 2)) AS int) AS BillingFrequency
FROM 
    orders a
        JOIN order_items b ON a.ORDER_ID = b.ORDER_ID
        JOIN order_item_options c ON b.ORDER_ITEM_ID = c.ORDER_ITEM_ID
        JOIN prices d ON c.PRICE_ID = d.PRICE_ID AND d.TO_OPTION_ID IN (189, 190, 191)
        JOIN product_options_vw e ON d.TO_OPTION_ID = e.OPTION_ID AND e.OPTION_ID IN (189, 190, 191)
WHERE
    e.OPTION_ID IN (189, 190, 191)
这项工作:

SELECT
     e.NAME
    , CAST(RTRIM(SUBSTRING(e.NAME, CHARINDEX('-', e.NAME) +2 , 2)) AS int) AS BillingFrequency
FROM 
    orders a
        JOIN order_items b ON a.ORDER_ID = b.ORDER_ID
        JOIN order_item_options c ON b.ORDER_ITEM_ID = c.ORDER_ITEM_ID
        JOIN prices d ON c.PRICE_ID = d.PRICE_ID AND d.TO_OPTION_ID IN (189, 190, 191)
        JOIN product_options_vw e ON d.TO_OPTION_ID = e.OPTION_ID AND e.OPTION_ID IN (189, 190, 191)
WHERE
    e.OPTION_ID IN (189, 190, 191)

我发现这两个查询都是相同的,只是在第二个查询中又添加了一列。奇怪的是,第二个查询不适合您

如果转换失败并且您可以看到

Try_CAST(RTRIM(SUBSTRING(e.NAME, CHARINDEX('-', e.NAME) +2 , 2)) AS int)
您可以看到所有可能导致此问题的null列。进一步的错误消息清楚地显示

将nvarchar值“ni”转换为数据类型int时,转换失败

所以你们可以试着只使用下面的部分,看看哪一个给你们一个ni的输出

RTRIM(子字符串(e.NAME,CHARINDEX('-',e.NAME)+2,2))


试着用
case
检查,然后
cast
@IvanStarostin-我做了类似的事情,并加入了一个额外的
ISNUMERIC
列。这很有效。删除它会使我再次出错。我真的很困惑,为什么添加一个专栏似乎突然添加了没有额外专栏就没有考虑的产品。我投了赞成票,因为我不知道TRY_CAST。但是,当我在将
CAST
更改为
TRY\u CAST
后运行查询时,它会毫无怨言地完成,并且不会显示任何无效数据。这一点让我开始感到困惑;WHERE条款应确保排除“其他”产品。然而,似乎强制转换操作在WHERE(或join)所做的过滤之前进行。不,它不是这样工作的,请参阅null。try\u CAST将确保强制转换在无效时不会失败,但结果将为null,但我也看不到null。只是我期望的数字。换句话说,返回的结果集中没有无效数据。