Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimize a NULL / NOT NULL flags PostgreSQL query

Tags:

postgresql

I am trying to get one record that contains boolean flags: true if a column in specific result set has at least one NOT NULL value and false if all the values are NULL.

Sample data of a result set

SELECT "my column 1", "my column 2", "my column 3", "my column 4", "my column 5" 
FROM my_data 
WHERE date BETWEEN :start AND :end

"my column 1" "my column 2" "my column 3" "my column 4" "my column 5"
   NULL          NULL          25.2          NULL          1.12
   15.28         NULL          NULL          NULL          2.25
   NULL          NULL          13.9          NULL          3.03
   359.00        NULL          125.5         NULL          4.15
   NULL          NULL          152.2         NULL          5.99
   NULL          NULL          NULL          NULL          6.35

In this case result should be:

"my column 1" "my column 2" "my column 3" "my column 4" "my column 5"
   t             f             t             f             t

A following PostgreSQL query does exactly what I need (actually it terminates each subquery as soon as first NOT NULL value has been detected), but could it be be optimized?:

WITH x AS (SELECT * FROM my_data WHERE date BETWEEN :start AND :end)

SELECT
    EXISTS(SELECT * FROM x WHERE "my column 1" IS NOT NULL) AS "my column 1",
    EXISTS(SELECT * FROM x WHERE "my column 2" IS NOT NULL) AS "my column 2",
    EXISTS(SELECT * FROM x WHERE "my column 3" IS NOT NULL) AS "my column 3",
    EXISTS(SELECT * FROM x WHERE "my column 4" IS NOT NULL) AS "my column 4",
    EXISTS(SELECT * FROM x WHERE "my column 5" IS NOT NULL) AS "my column 5"

I thought it could be written either shorter or universally, without mentioning each column name.

like image 552
Paul Avatar asked May 13 '26 08:05

Paul


1 Answers

Another alternative is to use the bool_or() aggregate which returns true if at lease one value is true.

SELECT bool_or("my column 1" is not null) AS "my column 1",
       bool_or("my column 2" is not null) AS "my column 2",
       bool_or("my column 3" is not null) AS "my column 3",
       bool_or("my column 4" is not null) AS "my column 4",
       bool_or("my column 5" is not null) AS "my column 5"
FROM my_data
WHERE date BETWEEN :start AND :end;

There is also the bool_and() aggregate that would return true only if all values are true.