CodeGym /课程 /SQL SELF /GREATEST() 和 LEAST() 函数以及 NULL

GREATEST() 和 LEAST() 函数以及 NULL

SQL SELF
第 10 级 , 课程 2
可用

今天我们要聊一个更细节但很重要的话题:GREATEST()LEAST() 这俩函数。你会学到怎么从多个列里找最大和最小值,还有最关键的,NULL 到底会怎么影响它们的结果。

如果你曾经在生活里找过最重要的东西(比如爱情、梦想工作或者最好吃的披萨),你肯定能秒懂 GREATEST()LEAST() 是干嘛的。这俩函数就是帮你在一堆“东西”里找最大或者最小的。只不过这里不是披萨,而是 PostgreSQL 里的数字、日期、字符串啥的。

GREATEST()

GREATEST() 会返回你传进去那堆值里最大的一个。

语法:

GREATEST(value1, value2, ..., valueN)

LEAST()

LEAST() 正好相反:它找最小的那个。

语法:

LEAST(value1, value2, ..., valueN)

例子:

假设我们有个表叫 students_scores,里面存着学生三次考试的分数:

student_id exam_1 exam_2 exam_3
1 85 90 82
2 NULL 76 89
3 94 NULL 88

GREATEST()LEAST() 来查:

SELECT
    student_id,
    GREATEST(exam_1, exam_2, exam_3) AS highest_score,
    LEAST(exam_1, exam_2, exam_3) AS lowest_score
FROM students_scores;

结果:

student_id highest_score lowest_score
1 90 82
2 89 NULL
3 94 NULL

NULL 怎么影响 GREATEST()LEAST()

现在到了最有意思的部分。表里除了正常的值,还可能有 NULL。 你应该知道,NULL 就是个谜一样的存在,代表没数据或者不知道值是多少。 那如果 NULL 混进了 GREATEST()LEAST() 里,PostgreSQL 会怎么处理呢?

NULL 的行为:

在 PostgreSQL 里,GREATEST()LEAST() 有点特殊:它们在找最大/最小值的时候会忽略 NULL注意: 只有一种情况会返回 NULL,那就是所有参数都是 NULL

例子:

SELECT
    GREATEST(10, 20, NULL, 5) AS greatest_value,
    LEAST(10, 20, NULL, 5) AS least_value;

结果:

greatest_value least_value
20 5

你看,NULL 被直接无视了,函数只看剩下的(10, 20, 5)然后返回最大和最小。

再看个例子,如果所有参数都是 NULL

例子:

SELECT
    GREATEST(NULL, NULL) AS greatest_nulls,
    LEAST(NULL, NULL) AS least_nulls;

结果:

greatest_nulls least_nulls
NULL NULL

怎么避免 NULL 带来的坑?

虽然 PostgreSQL 默认会忽略 NULL,但有时候你可能想让 NULL 当成某个具体的值(比如 0 或者别的默认值)来算最大/最小。这种情况就可以用 COALESCE() 函数。

COALESCE(arg1, arg2, ...) 会返回它参数列表里第一个不是 NULL 的值。这样你可以在把值传给 GREATEST()LEAST() 之前,先把 NULL 换成你想要的值。

例子 1:把 NULL 换成 0

比如说,我们想让没分数(NULL)的情况当成 0。那就用 COALESCE() 把它替换掉。

原始表长这样:

student_id exam_1 exam_2 exam_3
1 90 85 82
2 NULL 89 NULL
3 NULL NULL 94

SQL 查询:

SELECT
    student_id,
    GREATEST(
        COALESCE(exam_1, 0), 
        COALESCE(exam_2, 0), 
        COALESCE(exam_3, 0)
    ) AS highest_score,
    LEAST(
        COALESCE(exam_1, 0), 
        COALESCE(exam_2, 0), 
        COALESCE(exam_3, 0)
    ) AS lowest_score
FROM students_scores;

结果:

student_id highest_score lowest_score
1 90 82
2 89 0
3 94 0

例子 2:把 NULL 换成别的列的值

有时候你不想用固定值(比如 0),而是想用别的列的值。比如 exam_3 没分数时,就用 exam_1 的分数。

SELECT
    student_id,
    GREATEST(
        exam_1, 
        exam_2, 
        COALESCE(exam_3, exam_1)
    ) AS highest_score
FROM students_scores;

假设表是这样的:

student_id exam_1 exam_2 exam_3
1 90 85 82
2 NULL 89 NULL
3 70 NULL NULL

查询结果:

student_id highest_score
1 90
2 89
3 70

实战案例

案例 1:找最大折扣

order_id discount_1 discount_2 discount_3
101 5 10 7
102 NULL 3 8
103 15 NULL NULL
104 NULL NULL NULL

你在用 orders 这个表,每个订单可能有三种不同的折扣。你要找每个订单里最大的那个折扣。

SELECT
    order_id,
    GREATEST(discount_1, discount_2, discount_3) AS max_discount
FROM orders;

结果:

order_id max_discount
101 10
102 8
103 15
104 NULL

案例 2:找商品最低价

products 表里,商品价格有三种货币(USD、EUR、GBP)。你的任务是找出每个商品的最低价。

product_id price_usd price_eur price_gbp
1 100 95 80
2 NULL 150 140
3 200 NULL NULL
4 NULL NULL NULL
SELECT
    product_id,
    LEAST(price_usd, price_eur, price_gbp) AS lowest_price
FROM products;
product_id lowest_price
1 80
2 140
3 200
4 NULL

如果所有价格都是 NULL,结果也是 NULL

GREATEST()LEAST() 时常见的坑

坑 1:因为 NULL 得到意外的结果。

前面我们已经详细说了 NULL 在 PostgreSQL 里对 GREATEST()LEAST() 的影响。最大的问题是,有些同学习惯了别的数据库(那种只要有一个 NULL 就全都变 NULL 的),以为 PostgreSQL 也是这样。

怎么踩坑: 你可能会以为只要参数里有 NULL,函数就一定返回 NULL。结果你会不必要地对所有参数都用 COALESCE(),这样反而让 SQL 变复杂还慢,其实 PostgreSQL 里 NULL 本来就会被忽略。

坑 2:用 GREATEST()LEAST() 比较不兼容的类型。

GREATEST()LEAST() 这俩函数本来就是用来比同一种数据类型的值,或者能自动转换的类型。如果你硬要比完全不兼容的类型,肯定报错。

怎么踩坑: 你会收到个报错,说数据类型不兼容。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION