【问题标题】:SQL dividing 2 aggregates is giving invalid Operand data type errorSQL 划分 2 个聚合给出了无效的操作数数据类型错误
【发布时间】:2017-04-12 14:45:59
【问题描述】:

我使用 SUM 和 case 表达式来生成 2 个聚合值,然后我想将这 2 个数字相除以计算百分比。

我已尝试转换所有语句,但我不断收到错误:

消息 8117,第 16 级,状态 1,第 4 行 除法运算符的操作数数据类型 varchar 无效。

我很困惑它将第三个条件读取为 varchar - 我尝试将其转换为 Integer 和 Decimal,但收到相同的错误。这是我正在使用的代码:

SELECT 
  cast(SUM(case when Patient_Ethnic_Origin_Code = '99' then 1 end) as INTEGER)'Not Known'
, cast(SUM(case when Patient_Ethnic_Origin_Code IS NOT NULL then 1 end)as INTEGER)'All'
, cast('Not Known'/'All' as DECIMAL (10,2)) 'Calculation'

我也尝试过使用不同的方法,但这也给出了同样的错误:

SELECT 
'NotKnown'
,'All'
,'NotKnown' / 'All' as 'Calculation'

(SELECT
cast(SUM(case when Patient_Ethnic_Origin_Code = '99' then 1 end) as INTEGER)as 'NotKnown'
, cast(SUM(case when Patient_Ethnic_Origin_Code IS NOT NULL then 1 end)as INTEGER)as 'All'

FROM Inpatients.vw_IP_Spells

WHERE Discharge_Date BETWEEN '01/01/2017' AND '31/01/2017'
AND Admission_Method_National_Code LIKE '2%'
AND Patient_Ethnic_Origin_Code != 'Z'

)

谁能告诉我我的语法哪里出错了?

【问题讨论】:

    标签: sql-server-2008 tsql


    【解决方案1】:

    您不能在该子句中再次在 SELECT 子句中使用别名。我也不认为你需要那些演员表。这样的事情应该可以工作:

    SELECT
        SUM(CASE WHEN Patient_Ethnic_Origin_Code = '99' THEN 1 END) AS [Not Known],
        SUM(CASE WHEN Patient_Ethnic_Origin_Code IS NOT NULL THEN 1 END) AS [All],
        CAST(SUM(CASE WHEN Patient_Ethnic_Origin_Code = '99' THEN 1 END) AS DECIMAL(10,2)) /
        SUM(CASE WHEN Patient_Ethnic_Origin_Code IS NOT NULL THEN 1 END) [Calculation]
    FROM Inpatients.vw_IP_Spells
    WHERE ...
    

    您的第二次尝试(这也可能是一个好主意)失败了,因为您使用字符串文字来引用别名,即

    'NotKnown' / 'All' as 'Calculation'
    

    SQL Server 认为您正在尝试分割字符串,因此您看到了错误。如果您想使用子查询进行包装,可以尝试以下方法:

    SELECT t.[Not Known],
           t.[All],
           CAST(t.[Not Known] AS DECIMAL(10,2)) / t.[All] AS [Calculation]
    FROM
    (
        SELECT
            SUM(CASE WHEN Patient_Ethnic_Origin_Code = '99' THEN 1 END) AS [Not Known],
            SUM(CASE WHEN Patient_Ethnic_Origin_Code IS NOT NULL THEN 1 END) AS [All],
        FROM Inpatients.vw_IP_Spells
        WHERE ...
    ) t
    

    这有一个额外的好处,那就是使整个查询不那么冗长,并且可能更容易阅读。它也可能会降低性能,但也许你并不在意。

    【讨论】:

    • @Tim_Biegeleisen 感谢您的帮助。代码现在运行,但在 Calculation 字段中返回 0 数字。我将计算结果转换为小数,但仍然只返回 0.00。知道为什么计算不起作用吗?修改后的最后一行是:cast(SUM(CASE WHEN Patient_Ethnic_Origin_Code = '99' THEN 1 END) / SUM(CASE WHEN Patient_Ethnic_Origin_Code IS NOT NULL THEN 1 END) as DECIMAL (10,2))[Calculation]
    • @Jon295087 按照我的回答并注意,如果您想要将两个总和相除的小数结果,则需要将除数和/或除数转换为小数。您将两个整数相除,然后尝试将结果转换为小数。那是行不通的。您使用子查询的预感很好,希望我的回答能引导您朝着正确的方向前进。
    • @Tim_Biegeleisen 非常感谢,我使用了子查询方法,效果很好。这个数据集的性能还不错,所以这是一个奖励。我现在唯一的一点疑问是为什么十进制输出显示到小数点后 13 位,即使我只指定了 2 位。你有什么建议可能会让人不安吗? 100 - CAST(t.[NotKnown] AS DECIMAL(10,2)) / t.[All] * 100 AS [Calculation]
    • DECIMAL(10,2) 仅指列的精度,不一定指其呈现方式。再次投射整个表达式应该可以工作,即CAST(100 - CAST(t.[NotKnown] AS DECIMAL(10,2)) / t.[All]*100 AS DECIMAL(10,2)) ...但我不确定我有一个很好的答案,为什么需要这样做。
    • @Tim_Biegeleisen - 渲染正确。再次感谢您的时间和讨论
    猜你喜欢
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-03
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多