下面是一本书上SQL应用MIN()函数获取tb_min表中number1和number2字段的最小值的代码。
请问,获取最小值还要减号干什么?看不明白,是不是这段代码有错误。
SELECT MIN(((number1+number2)-ABS(number1-number2))/2) AS '最小数' FROM (SELECT * FROM tb_min WHERE (number1>0 AND number2>0)) a;
您这个问题问得很好!这段代码没有错误,它巧妙地利用了数学公式来求两个数的最小值。
核心原理:求两数最小值的数学公式
sql
MIN((number1 + number2 - ABS(number1 - number2)) / 2)
这个公式的本质是:两个数的和减去它们的差,再除以2,得到的就是较小的那个数。
数学推导
假设有两个数 a 和 b:
如果 a ≥ b:
(a + b - |a - b|)/2 = (a + b - (a - b))/2 = (2b)/2 = b(最小值)如果 a < b:
(a + b - |a - b|)/2 = (a + b - (b - a))/2 = (2a)/2 = a(最小值)
具体例子
sql
-- 假设 number1=10, number2=3(10 + 3 - ABS(10-3))/2 = (13 - 7)/2 = 6/2 = 3 ✓-- 假设 number1=5, number2=20 (5 + 20 - ABS(5-20))/2 = (25 - 15)/2 = 10/2 = 5 ✓
为什么不用直接的 MIN()?
您可能会问:为什么不直接写 MIN(number1, number2)?
因为标准 SQL 中的 MIN() 函数是聚合函数,用于返回一列中的最小值,不能直接比较同一行中的两个字段。
sql
-- 错误用法(大多数数据库不支持)SELECT MIN(number1, number2) FROM tb_min; -- ❌ 语法错误-- 正确但繁琐的替代方案SELECT CASE WHEN number1 < number2 THEN number1 ELSE number2 END AS min_valueFROM tb_min;
这段代码的整体逻辑
sql
SELECT MIN(计算出的每行较小值) AS '最小数'FROM (SELECT * FROM tb_min WHERE number1>0 AND number2>0) a;
子查询:筛选出 number1 和 number2 都大于0的记录
公式计算:对每行数据计算出两个数中的较小值
MIN()聚合:从所有较小值中再找出全局最小值
验证示例
sql
-- 测试数据CREATE TABLE tb_min (number1 INT, number2 INT);INSERT INTO tb_min VALUES (10, 3), (5, 20), (8, 8), (15, 7);-- 执行查询SELECT number1, number2, (number1 + number2 - ABS(number1 - number2))/2 AS per_row_min, MIN((number1 + number2 - ABS(number1 - number2))/2) OVER() AS global_minFROM tb_min;
结果:
number1 | number2 | per_row_min | global_min |
10 | 3 | 3 | 3 |
5 | 20 | 5 | 3 |
8 | 8 | 8 | 3 |
15 | 7 | 7 | 3 |
总结
这段代码没有错误,是巧妙的数学解法
用减号是为了通过数学公式求出每行的最小值
现代数据库有更简洁的方案:
LEAST()函数(MySQL)或MIN()作为标量函数(SQL Server 2022+)
sql
-- 更简洁的写法(如果数据库支持)SELECT MIN(LEAST(number1, number2)) AS '最小数'FROM tb_min WHERE number1>0 AND number2>0;
这种教科书上的写法展示了 SQL 与数学思维的结合,虽然略显复杂,但很有教育意义