如何在SQL Server中实现分数加法运算
SQL Server分数格式数值加法实现方案
要实现分数格式的加法并保留分数输出,核心逻辑分为四步:
- 拆分所有待计算分数字符串,分别提取分子、分母
- 计算所有分母的最小公分母,将所有分数统一为同分母后求和得到总分子
- 对总分子和最小公分母求最大公约数完成约分
- 按要求格式化输出结果,分子可被分母整除时仅输出整数
1. 创建最大公约数(GCD)计算函数
CREATE FUNCTION dbo.GetGCD(@a INT, @b INT) RETURNS INT AS BEGIN -- 辗转相除法求最大公约数 WHILE @b <> 0 BEGIN DECLARE @temp INT = @b SET @b = @a % @b SET @a = @temp END RETURN ABS(@a) END GO
2. 创建最小公倍数(LCM)计算函数
CREATE FUNCTION dbo.GetLCM(@a INT, @b INT) RETURNS INT AS BEGIN -- 最小公倍数 = 两数乘积 / 最大公约数,先除后乘避免溢出 RETURN (@a / dbo.GetGCD(@a, @b)) * @b END GO
3. 分数求和查询示例
假设存储分数的表名为FractionTable,分数字段名为FractionValue,格式为分子/分母:
WITH SplitFractions AS ( -- 拆分每个分数的分子、分母 SELECT CAST(LEFT(FractionValue, CHARINDEX('/', FractionValue) - 1) AS INT) AS Numerator, CAST(RIGHT(FractionValue, LEN(FractionValue) - CHARINDEX('/', FractionValue)) AS INT) AS Denominator FROM FractionTable ), CalculateLCM AS ( -- 递归计算所有分母的最小公分母 SELECT MIN(Denominator) AS CurrentLCM, 1 AS RowNum FROM SplitFractions UNION ALL SELECT dbo.GetLCM(cl.CurrentLCM, sf.Denominator), cl.RowNum + 1 FROM CalculateLCM cl JOIN ( SELECT Denominator, ROW_NUMBER() OVER (ORDER BY Denominator) AS rn FROM SplitFractions ) sf ON sf.rn = cl.RowNum + 1 ), FinalLCM AS ( -- 取最终的最小公分母 SELECT TOP 1 CurrentLCM AS CommonDenominator FROM CalculateLCM ORDER BY RowNum DESC ), TotalNumerator AS ( -- 同分母求和得到总分子 SELECT SUM(Numerator * (fl.CommonDenominator / Denominator)) AS SumNumerator FROM SplitFractions sf CROSS JOIN FinalLCM fl ) -- 约分后格式化输出 SELECT CASE WHEN SumNumerator % CommonDenominator = 0 THEN CAST(SumNumerator / CommonDenominator AS VARCHAR(20)) ELSE CAST(SumNumerator / dbo.GetGCD(SumNumerator, CommonDenominator) AS VARCHAR(20)) + '/' + CAST(CommonDenominator / dbo.GetGCD(SumNumerator, CommonDenominator) AS VARCHAR(20)) END AS FractionSum FROM TotalNumerator tn CROSS JOIN FinalLCM fl -- 分数数量超过100时打开下方注释解除递归限制 -- OPTION (MAXRECURSION 0)
测试效果
- 待计算分数为
1/4、2/4时,输出结果为3/4 - 待计算分数为4个
1/4时,输出结果为1 - 待计算分数为
1/3、1/6时,输出结果为1/2
注意事项
- 需提前校验分数字符串格式合法性,避免出现无
/、分母为0等异常 - 分数数值较大时,可将函数中
INT类型替换为BIGINT避免溢出 - 支持负分数计算,分子可直接带负号存储即可正常运算
内容的提问来源于stack exchange,提问作者Anurag
相关产品推荐
相关产品推荐

