You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在SQL Server中计算表格内人员体重的百分比增减

解决SQL Server中体重百分比计算异常的问题

别担心,刚重新接触SQL Server进阶内容遇到问题太正常了,我帮你排查一下这个体重变化百分比计算的问题~

问题根源:计算优先级错误

你得到异常结果(比如Resident 1的83.1体重对应-16.90)的核心原因是算术运算优先级搞反了!

在你的CASE表达式里,当前的计算逻辑是:

[Weight] - FIRST_VALUE([Weight]) / FIRST_VALUE([Weight]) * 100.0

因为除法和乘法的优先级高于减法,实际执行顺序是:
[Weight] - ( (初始体重 / 初始体重) * 100 ) → 也就是 体重 - 100,这就导致了83.1-100=-16.90这种完全不符合预期的结果。

修正方案

我们需要给体重差值加上括号,确保先计算当前体重和初始体重的差,再除以初始体重乘以100。同时可以优化代码,把初始体重提前在CTE中计算,避免重复调用FIRST_VALUE函数,提升效率。

修正后的完整代码

;WITH cte AS (
    SELECT 
        ServiceUserID, 
        ra.PersonID, 
        ServiceUser, 
        cn.DateDone, 
        TRY_CAST(
            LEFT(
                SUBSTRING(cn.Fragment, PATINDEX('%[0-9.-]%', cn.Fragment), 8000), 
                PATINDEX('%[^0-9.-]%', SUBSTRING(cn.Fragment, PATINDEX('%[0-9.-]%', cn.Fragment), 8000) + 'X') - 1
            ) AS REAL
        ) AS [Weight], 
        ra.ScoreMeaning
    FROM [JSONCareNotes-HOME] cn 
    LEFT OUTER JOIN [JSONRAs-HOME] ra ON ra.PersonID = cn.ServiceUserID 
    WHERE cn.SliderData LIKE '%weigh%' AND cn.Fragment NOT LIKE '%weighed%'
),
cte_initial_weight AS (
    SELECT 
        ServiceUser,
        DateDone,
        [Weight],
        -- 提前计算每个用户的初始体重
        FIRST_VALUE([Weight]) OVER (PARTITION BY [ServiceUser] ORDER BY DateDone ASC) AS InitialWeight
    FROM cte
    WHERE [Weight] IS NOT NULL -- 修正WHERE条件:REAL类型不能和空字符串比较
)
SELECT 
    ServiceUser, 
    DateDone, 
    [Weight],
    CASE 
        WHEN InitialWeight = 0 THEN 0.00 -- 避免除以0
        ELSE CONVERT(numeric(10, 2), ([Weight] - InitialWeight) / InitialWeight * 100.0)
    END AS [Percentage]
FROM cte_initial_weight
ORDER BY ServiceUser, DateDone ASC;

关键修正点说明

  1. 计算逻辑修正:给([Weight] - InitialWeight)加上括号,确保先算差值,再做除法和乘法,得到正确的百分比变化值。
  2. 优化初始体重计算:新增cte_initial_weight子句,一次性计算每个用户的初始体重,避免重复调用FIRST_VALUE,提升查询效率。
  3. 修正WHERE条件:原条件NOT([Weight] IS NULL) OR [Weight] = ' '存在错误,因为[Weight]是REAL类型,无法和字符串' '比较,直接用[Weight] IS NOT NULL过滤空值即可。

验证结果

以Resident 1为例,如果初始体重是83.1:

  • 第一次记录的百分比应该是(83.1-83.1)/83.1*100 = 0.00
  • 如果后续某条记录体重是85.0,百分比就是(85.0-83.1)/83.1*100 ≈ 2.29
    这样结果就符合预期了。

内容的提问来源于stack exchange,提问作者Ant

火山引擎 最新活动