【问题标题】:Using min with cast nvarchar to float with group by throws error in converting使用 min 和 cast nvarchar 与 group by 一起浮动会在转换中引发错误
【发布时间】:2019-01-24 07:05:33
【问题描述】:

我有一个选择查询,它执行一些连接和几个返回 3 个数值的 where 子句。此列的类型是 nvarchar,我正在尝试将其转换为 float,但失败并抛出异常“Error convert data type nvarchar to float”。我无法用下面的虚拟表重现错误,但这是我目前所拥有的,它适用于这个虚拟数据,但不适用于我的 select 语句结果:

CREATE TABLE #TEMP(Id nvarchar(10), dept nvarchar(10))
INSERT INTO #TEMP VALUES('NA', 'cs')
INSERT INTO #TEMP VALUES('1550 ', 'it')
INSERT INTO #TEMP VALUES(' 1665', 'it')
INSERT INTO #TEMP VALUES('NA', 'cs')
INSERT INTO #TEMP VALUES(' 1750 ', 'it')
INSERT INTO #TEMP VALUES('1400', 'cs')

SELECT COUNT(Id), MAX(CAST(Id AS FLOAT))  FROM #TEMP
WHERE dept = 'it'
GROUP BY dept
--WHERE Id NOT IN ('NA', '-')
DROP TABLE #TEMP

此外,当我颠倒我的施法顺序并找出最小值/最大值时,它工作得很好。

CAST(MIN(Id) AS FLOAT) 

如果我们先进行强制转换然后使用聚合函数会出现问题,还是使用 group by 子句以这种方式进行查询是否存在问题?

请注意,我的表格将在结果中包含 'NA'、'-' 和空格。

【问题讨论】:

  • 你的预期输出是什么?
  • 我的预期输出是将查询中的最小值或最大值作为浮点数返回。但更重要的是,我想找出为什么在我先投射然后进行聚合时抛出异常的根本原因
  • 现在请检查我的答案。
  • 根本原因是你在某处有一些不可靠的数据,首先转换然后最大化转换每个值。先取最大值,然后再施放只是施放明显有效的最大值。您可以使用 try_convert 函数找到不可靠的数据,该函数将为未转换的行返回 null。
  • 我怀疑我们是否可以在不访问实时数据的情况下提供帮助,因为错误很明显 Error converting data type nvarchar to float 所以有一些字符串数据当前没有转换为浮点值 - 你只需要找到它。我不知道您有多少记录,但您可以通过消除正确值的过程找到它。设计数据库时使用正确数据类型的充分理由:)

标签: sql-server aggregate-functions


【解决方案1】:

你可以试试下面的case语句

CREATE TABLE #TEMP(Id nvarchar(10), dept nvarchar(10))
INSERT INTO #TEMP VALUES('NA', 'cs')
INSERT INTO #TEMP VALUES('1550 ', 'it')
INSERT INTO #TEMP VALUES(' 1665', 'it')
INSERT INTO #TEMP VALUES('NA', 'cs')
INSERT INTO #TEMP VALUES(' 1750 ', 'it')
INSERT INTO #TEMP VALUES('1400', 'cs')

SELECT dept, 
MAX(CAST(case Id when 'NA' then 0 else Id end AS FLOAT))  
FROM #TEMP
GROUP BY dept
DROP TABLE #TEMP

输出如下图

dept    (No column name)
------------------------
cs      1400
it      1750

你可以找到现场演示here

【讨论】:

  • 我在 UDF 中有 select 语句,它使用 case a lil 不同,因为我有多个场景并且它可能会增加。但试图找出我现有解决方案失败的根本原因。
  • 错误在Select CAST(Id AS FLOAT) FROM #TEMP这一行,因为NA不能转换为浮点数。您还可以使用 case 语句将值传递给 UDF。
  • 你应该写简单的 MAX(Id) 而不是强制转换然后它会起作用。\
  • 是的,但前提是我的选择将具有该值。在我的情况下,我只看到 3 个数值,即 1550、1665、1750,但它仍然失败并出现同样的错误。
【解决方案2】:

您可以使用TRY_CONVERT 使其始终像以下那样工作。

SELECT COUNT(Id), MAX(TRY_CONVERT(float, id))  FROM #TEMP
WHERE dept = 'it'
GROUP BY dept

另外,当我颠倒我的施法顺序并找出 最小/最大效果很好。

这是有效的,因为 MAX 也适用于 varchar/nvarchar 列。它会为您的场景返回一个数字字符串作为最大值,您可以将其转换为浮点数。相反的情况不起作用,因为第一次转换将在 MAX 之前进行,如果列不是有效数字,则转换将失败。

【讨论】:

  • 是的,这也有效,但请帮我找出它在我现有场景中失败的根本原因。
  • 所以在我的场景中,max 也失败了。我知道我的问题没有提供重现,但这是我能解释我的问题的最接近的方法
  • MAX 不会失败,它适用于字符串和数字。所以它永远不会失败。
  • 是的,它不会失败,但由于某种原因,它在我的场景和数值中失败了(我不知道它们是否有一些特殊的字符并试图找出它)。这就是为什么我在我的表中添加了空格,但 CAST 会处理它。
【解决方案3】:

你可以用这个 CAST(cast(replace(Id,'NA','') as int) AS FLOAT)

【讨论】:

    猜你喜欢
    • 2013-05-19
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多