关于 PostgreSQL 中的 COALESCE 和处理空值

About COALESCE in PostgreSQL and handling Null Values

我正在使用 PostgreSQL 练习 SQL,但我在使用 COALESCE 时遇到了困难,也许有人可以告诉我哪里出错了。

我有一个包含四列的 table:标题、height_cm、length_cm 和 width_cm。我想乘以最后三个并得到“大小”列。问题是整个数据集有许多我想跳过的 NULL 值和 0,以及 return 三列可能的最大值(即如果只有高度有值,return 那个值,如果三列的值乘以三)。如果没有列具有值 return“未找到任何值”。

我无法管理“跳过”Null 值(我还没有真正从 0 开始,因为我卡在了开头)。我以为这样就可以了,但是没有用。

 SELECT title, height_cm, length_cm, width_cm, 
        COALESCE(
        height_cm * length_cm * width_cm, 
        length_cm * width_cm, 
        height_cm * length_cm, 
        height_cm * width_cm, 
        height_cm, 
        length_cm, 
        width_cm, 'NO VALUE FOUND') AS size
FROM artworks
ORDER BY size ASC
LIMIT 10

首先,系统不识别“NO VALUE FOUND”(但是当我添加一个0时,它识别它),其次,当我取出文本时,系统仍然认为是NULL值。我能够让它工作添加

WHERE height_cm IS NOT NULL AND length_cm IS NOT NULL AND width_cm IS NOT NULL

但我认为 COALESCE 的主要思想是能够跳过 NULL 值。有什么建议吗?

关于0,如果我加上:

WHERE height_cm != 0 AND length_cm != 0 AND width_cm != 0

我丢失了有值但也有一个 0 的行。

谢谢!

使用答案中的解决方案进行编辑

最后我用了一个CTE结合下面帮助过的人的回答,这是最终的查询:

WITH query AS (SELECT title, height_cm, length_cm, width_cm, 
        (CASE WHEN height_cm IS NULL AND length_cm IS NULL AND width_cm IS NULL
        THEN 0
        ELSE (COALESCE(height_cm, 1) * COALESCE(length_cm, 1) * COALESCE(width_cm, 1))
        END) AS size
        FROM artworks)
        
SELECT *
FROM query
WHERE size > 0
ORDER BY size ASC
LIMIT 10

另一方面,“未找到值”是字符串类型 0 是数字,这就是为什么当您使用 0 时它不会产生问题,因为在 0 的情况下,该列的所有数据都是数字数据类型但是当你正在尝试使用字符串它已经创建了混合两种不同数据类型的问题,sql引擎

不允许

听起来你真正想在这里使用的函数是GREATEST:

SELECT
    title,
    height_cm,
    length_cm,
    width_cm, 
    COALESCE(
        GREATEST(
            height_cm * length_cm * width_cm,
            length_cm * width_cm,
            height_cm * length_cm,
            height_cm * width_cm,
            height_cm,
            length_cm,
            width_cm)::text, 'NO VALUE FOUND') AS size
FROM artworks
ORDER BY size
LIMIT 10;

GREATEST 函数将自动选取最大的 NULL 值。因此,对于高度、长度和宽度恰好同时为 NULL 的情况,您在这里只需要 COALESCE 即可。

传递给 coalesce 的所有元素的数据类型应该相同,但我会将 coalesce 应用到每个列 separately 并使用默认值 1 如果是 null:

coalesce(height_cm, 1) * coalesce(length_cm, 1) * coalesce(width_cm, 1) as size

这在逻辑上与您编写的代码相同。

如果它们是 all null,您需要进行特殊检查,为此您也可以(滥用)使用 coalesce

case
    when coalesce(height_cm, length_cm, width_cm) is null then null -- or 0
    else coalesce(height_cm, 1) * coalesce(length_cm, 1) * coalesce(width_cm, 1)
end as size

您必须选择 null 或一些特殊值(例如 0),当它们都是 null 时。您可以根据需要它作为“未找到任何值”呈现给用户。

我同意波西米亚人关于使用单一表达方式的观点。但是,我认为你想要的最终表达式 returns 是一个字符串:

(case when height_cm is null and length_cm is null and width_cm is null
      then 'NO VALUE FOUND'
      else (coalesce(height_cm, 1) * coalesce(length_cm, 1) * coalesce(width_cm, 1))::text
 end) as size

或者,只接受一个 NULL 值,这意味着该值不可用。