简体   繁体   English

在 Postgres 中:在多个值上使用“IS DISTINCT FROM”的最简洁方法是什么?

[英]In Postgres: What is the most concise way to use `IS DISTINCT FROM` on multiple values?

I'm trying to find all rows that have an enum column that is either NULL or otherwise distinct from a given set of enum values.我正在尝试查找具有枚举列的所有行,该列要么是 NULL,要么与给定的一组枚举值不同。 I can do it with a lot of IS DINSTINCT FROM calls, but it's really verbose and I'd rather use NOT IN() syntax, but the NULL throws that off.我可以用很多IS DINSTINCT FROM调用来做到这一点,但它真的很冗长,我宁愿使用NOT IN()语法,但NULL会抛弃它。

Here is an example of what I want to do in SQL, from this fiddle: http://sqlfiddle.com/#!17/dfae4d/8这是我想在 SQL 中做的一个例子,来自这个小提琴: http://sqlfiddle.com/#!17/dfae4d/8


    CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
    CREATE TABLE people (
        name text,
        current_mood mood,
        current_mood_as_text varchar
    );
    insert into people values('Mr Happy', 'happy', 'happy');
    insert into people values('Mr Sad', 'sad', 'sad');
    insert into people values('Mr Null', NULL, NULL);

    -- This doesn't return MrUnknown because of the NULL value:
    select * from people where current_mood NOT IN ('happy');

    -- This works great, and includes Mr Null:
    select * from people where current_mood IS DISTINCT FROM 'happy';

    -- But If I want to start comparing to multiple moods, it gets more verbose fast:
    SELECT * FROM people 
    WHERE current_mood IS DISTINCT FROM 'happy' AND
    current_mood IS DISTINCT FROM 'sad';

    -- You can't write this, but it's kinda what I want:
    -- SELECT * FROM people 
    -- WHERE current_mood IS DISTINCT FROM ('happy', 'sad');

    -- For the non enum column, I could do this to make my intention and code clear and concise
    SELECT * FROM people 
    WHERE coalesce(current_mood_as_text, '') NOT IN ('happy', 'sad');

    -- But if I write this, I get an error because '' is not a valid enum value
    -- SELECT * FROM people 
    -- WHERE coalesce(current_mood, '') NOT IN ('happy', 'sad');

Is there another way to make this sort of multiple comparison more concise?还有另一种方法可以使这种多重比较更简洁吗?

The solution with coalesce() :使用coalesce()的解决方案:

select * 
from people 
where coalesce(current_mood not in ('happy', 'sad'), true)

SQLFiddle. SQLFiddle。

Yet another way:还有一种方式:


SELECT * FROM people 
WHERE NOT EXISTS (
  SELECT FROM (VALUES ('happy'::mood), ('sad')) v(m)
  WHERE people.current_mood = v.m
);

Cleanest(IMO) way is to use VALUES() inside a CTE and perform NOT EXISTS() on that table expression: Cleanest(IMO) 方法是在 CTE 中使用VALUES()并对该表表达式执行NOT EXISTS()


WITH m(m) AS ( VALUES( 'happy'::mood) )
SELECT *
FROM people p
WHERE NOT EXISTS (
        SELECT * FROM m
        WHERE m.m = p.current_mood
        );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM