计算行中的非空列

Count not-null columns in row

我正在尝试确定填充的特定列的数量,这是我正在尝试执行的操作:

  foo := COALESCE(.col1, '') || ' ' ||
    COALESCE(.col2, '') || ' ' ||
    COALESCE(.col3, '') || ' ' ||
    COALESCE(.col4, '');
  foo := REPLACE(foo, var, ' ');
  words := string_to_array(foo, ' ');
  RETURN array_length(words, 1);

其中var是白色的space,\s好像不行。我愿意接受任何其他查找非零列数的方法。

像这样的东西会起作用,而且更容易。

create table foo (
  id integer primary key,
  col1 text,
  col2 text,
  col3 text);

insert into foo values 
  (0, null, null, null),
  (1, null, null, 'aa'),
  (2, null, 'aa', 'bb'),
  (3, 'aa', 'bb', 'cc');

select id, 
  case when col1 is null then 1 else 0 end +
  case when col2 is null then 1 else 0 end +
  case when col3 is null then 1 else 0 end as null_columns
from foo;

生产

0 3
1 2
2 1
3 0

SQL Fiddle: http://sqlfiddle.com/#!15/2ab3c/7/0

在 Postgres 9.3 或更高版本中使用 JSON functions,您无需拼出所有列 - 甚至不知道它们 - 即可做到这一点:

SELECT t.*, count(value)::int AS notnull_ct   -- cast to int is optional
FROM   tbl t, json_each_text(row_to_json(t))  -- implicit LATERAL join
-- WHERE key LIKE 'col%' -- optionally consider only selected columns
GROUP  BY tbl_id;        -- PK column
默认为

json_each_text() returns (key, value)。在命名冲突的情况下使用不同的别名和/或 table-qualify 名称。如果您只对选定的列感兴趣,则可以在 WHERE 子句中过滤列名。

或者使用附加模块 hstore 达到同样的目的,至少从 Postgres 8.3:

开始可用
  • Key value pair in PostgreSQL

SELECT t.*, count(v)::int AS notnull_ct
FROM   tbl t, svals(hstore(t)) v
GROUP  BY tbl_id;

主要特点是 count() 不计算 NULL 值(也从不计算 returns NULL)。正是您所需要的。

你可以把它封装在一个函数中。具有多态输入类型的简单 SQL 函数可以完成这项工作:

CREATE OR REPLACE FUNCTION f_count_notnull_in_row(ANYELEMENT)
  RETURNS int LANGUAGE sql IMMUTABLE AS
'SELECT count(value)::int
 FROM   json_each_text(row_to_json())';

致电:

SELECT *, f_count_notnull_in_row(t)
FROM  tbl t;

SQL Fiddle(重复使用 Bill 的设置)。

考虑以 table 为例

| id |   col1 |   col2 |   col3 |
|----|--------|--------|--------|
|  0 | (null) | (null) | (null) |
|  1 | (null) | (null) |     aa |
|  2 | (null) |     aa |     bb |
|  3 |     aa |     bb |     cc |

使用 unnest() 和 array() 获得所需的输出。

SELECT id,count(col) not_null_col_cnt
FROM (SELECT id,unnest(array [col1,col2,col3]) col
      FROM foo
     ) t
GROUP BY id
ORDER BY id

结果:

| id | not_null_col_cnt |
|----|------------------|
|  0 |                0 |
|  1 |                1 |
|  2 |                2 |
|  3 |                3 |

您可以使用简单的转换:

SELECT id, 
 (col1 IS NULL)::int + (col2 IS NULL)::int  + (col3 IS NULL)::int  As null_number
FROM table_name;

SqlFiddleDemo

输出:

╔═════╦═════════╦═════════╦═════════╦═════════════╗
║ id  ║  col1   ║  col2   ║  col3   ║ null_number ║
╠═════╬═════════╬═════════╬═════════╬═════════════╣
║  1  ║ a       ║ b       ║ c       ║           0 ║
║  2  ║ a       ║ b       ║ (null)  ║           1 ║
║  3  ║ a       ║ (null)  ║ (null)  ║           2 ║
║  4  ║ (null)  ║ (null)  ║ (null)  ║           3 ║
╚═════╩═════════╩═════════╩═════════╩═════════════╝